summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/hybrid-latex/doc
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/hybrid-latex/doc
Initial commit
Diffstat (limited to 'macros/latex/contrib/hybrid-latex/doc')
-rw-r--r--macros/latex/contrib/hybrid-latex/doc/hybrid.pdfbin0 -> 240299 bytes
-rw-r--r--macros/latex/contrib/hybrid-latex/doc/hybrid.pytex36
-rw-r--r--macros/latex/contrib/hybrid-latex/doc/hybrid.sty77
-rw-r--r--macros/latex/contrib/hybrid-latex/doc/hybrid.tex1089
4 files changed, 1202 insertions, 0 deletions
diff --git a/macros/latex/contrib/hybrid-latex/doc/hybrid.pdf b/macros/latex/contrib/hybrid-latex/doc/hybrid.pdf
new file mode 100644
index 0000000000..aa4d14d230
--- /dev/null
+++ b/macros/latex/contrib/hybrid-latex/doc/hybrid.pdf
Binary files differ
diff --git a/macros/latex/contrib/hybrid-latex/doc/hybrid.pytex b/macros/latex/contrib/hybrid-latex/doc/hybrid.pytex
new file mode 100644
index 0000000000..ad2d228b6a
--- /dev/null
+++ b/macros/latex/contrib/hybrid-latex/doc/hybrid.pytex
@@ -0,0 +1,36 @@
+\pytag{ans.01}{%
+e^{- x}%
+}
+\pytag{ans.02}{%
+1 - x + \frac{x^{2}}{2} - \frac{x^{3}}{6} + \mathcal{O}\left(x^{4}\right)%
+}
+\pytag{ans.03}{%
+1 - x + \frac{x^{2}}{2} - \frac{x^{3}}{6} + \frac{x^{4}}{24} - \frac{x^{5}}{120} + \frac{x^{6}}{720} - \frac{x^{7}}{5040} + \mathcal{O}\left(x^{8}\right)%
+}
+\pytag{Pascal}{%
+\m{1}\cr%
+\m{1}\m{1}\cr%
+\m{1}\m{2}\m{1}\cr%
+\m{1}\m{3}\m{3}\m{1}\cr%
+\m{1}\m{4}\m{6}\m{4}\m{1}\cr%
+\m{1}\m{5}\m{10}\m{10}\m{5}\m{1}\cr%
+\m{1}\m{6}\m{15}\m{20}\m{15}\m{6}\m{1}\cr%
+}
+\pytag{fun}{%
+\frac{1}{x + 1}%
+}
+\pytag{ans.101}{%
+1 - x + x^{2} - x^{3} + x^{4} - x^{5} + \mathcal{O}\left(x^{6}\right)%
+}
+\pytag{ans.102}{%
+1 - x + x^{2} - x^{3} + x^{4} - x^{5} + x^{6} - x^{7} + x^{8} + \mathcal{O}\left(x^{9}\right)%
+}
+\pytag{ans.103}{%
+1 - x + x^{2} - x^{3} + x^{4} - x^{5} + x^{6} - x^{7} + x^{8} - x^{9} + x^{10} - x^{11} + \mathcal{O}\left(x^{12}\right)%
+}
+\pytag{ans.104}{%
+1 - x + x^{2} - x^{3} + x^{4} - x^{5} + x^{6} - x^{7} + x^{8} - x^{9} + x^{10} - x^{11} + x^{12} - x^{13} + x^{14} + \mathcal{O}\left(x^{15}\right)%
+}
+\pytag{ans.105}{%
+1 - x + x^{2} - x^{3} + x^{4} - x^{5} + x^{6} - x^{7} + x^{8} - x^{9} + x^{10} - x^{11} + x^{12} - x^{13} + x^{14} - x^{15} + x^{16} - x^{17} + x^{18} - x^{19} + x^{20} - x^{21} + x^{22} - x^{23} + x^{24} - x^{25} + x^{26} - x^{27} + x^{28} - x^{29} + \mathcal{O}\left(x^{30}\right)%
+}
diff --git a/macros/latex/contrib/hybrid-latex/doc/hybrid.sty b/macros/latex/contrib/hybrid-latex/doc/hybrid.sty
new file mode 100644
index 0000000000..d0c6efedeb
--- /dev/null
+++ b/macros/latex/contrib/hybrid-latex/doc/hybrid.sty
@@ -0,0 +1,77 @@
+\usepackage{pylatex}
+\usepackage{amsmath}
+\usepackage{amssymb}
+\usepackage{listings}
+\usepackage{xcolor}
+\usepackage{graphicx}
+\usepackage{geometry}
+\usepackage[toc]{multitoc}
+\usepackage{hyperref}
+\usepackage{breqn}
+\usepackage{longtable}
+
+\renewcommand*{\multicolumntoc}{2}
+\setlength{\columnseprule}{0pt}
+\setlength{\columnsep}{25pt}
+
+\hypersetup{colorlinks=true,filecolor=magenta}
+% \geometry{papersize={210mm,297mm},hmargin=2cm,tmargin=1.0cm,bmargin=1.5cm}
+% \geometry{papersize={210mm,297mm},hmargin=2cm,tmargin=1.0cm,bmargin=2.0cm}
+\geometry{papersize={210mm,297mm},hmargin=2cm,tmargin=1.5cm,bmargin=2.0cm}
+% \geometry{papersize={210mm,297mm},hmargin=2.5cm,tmargin=1.5cm,bmargin=2.5cm}
+
+\definecolor{grey95}{rgb}{0.95,0.95,0.95}
+
+\parindent=0pt
+\parskip=8pt plus 2pt minus 1pt
+
+\def\tts{\tt\small}
+
+\def\MYn{\vrule height 0pt depth 5pt width 0pt}
+\def\MYN{\vrule height 15pt depth 0pt width 0pt}
+
+\def\MyPar#1#2{\parbox[t]{#1\textwidth}{\sloppy \MYN#2\MYn}}
+
+\newbox\SlashPy
+\setbox\SlashPy=\hbox{\tts\verb|\Py|}
+
+\newbox\SlashPyStar
+\setbox\SlashPyStar=\hbox{\tts\verb|\Py*|}
+
+\def\PythonTeX{{\tts PythonTeX}}
+\def\SymPyTeX{{\tts SymPyTeX}}
+\def\SageTeX{{\tts SageTeX}}
+
+\def\pyLaTeX{{\tts pyLaTeX}}
+\def\matLaTeX{{\tts matLaTeX}}
+\def\mmaLaTeX{{\tts mmaLaTeX}}
+\def\mplLaTeX{{\tts mplLaTeX}}
+\def\cdbLaTeX{{\tts cdbLaTeX}}
+
+\def\bgcolour#1{\lstset{backgroundcolor=\color{#1}}}
+
+\def\pythonstyle{\lstset{%
+language=python,
+gobble=2,
+basicstyle={\tts},basewidth={0.50em},
+numbers=none,numberstyle=\tiny,numbersep=10pt,
+aboveskip=0pt,belowskip=0pt,
+frame=none,framesep=0pt,framerule=0pt,
+}}
+
+\def\latexstyle{\lstset{%
+language={[LaTeX]TeX},
+gobble=2,
+basicstyle={\tts},basewidth={0.50em},
+numbers=none,numberstyle=\tiny,numbersep=10pt,
+aboveskip=0pt,belowskip=0pt,
+frame=none,framesep=0pt,framerule=0pt,
+texcsstyle=*\bfseries\color{blue},
+stringstyle=\color{green},
+commentstyle=\color{blue}\slshape,
+}}
+
+\def\lstlatex#1{\def\latexmore{\lstset{#1}}}
+\lstlatex{}
+
+\lstnewenvironment{latex}{\begingroup\latexstyle\latexmore}{\endgroup}
diff --git a/macros/latex/contrib/hybrid-latex/doc/hybrid.tex b/macros/latex/contrib/hybrid-latex/doc/hybrid.tex
new file mode 100644
index 0000000000..c226321e90
--- /dev/null
+++ b/macros/latex/contrib/hybrid-latex/doc/hybrid.tex
@@ -0,0 +1,1089 @@
+\documentclass[12pt]{article}
+\usepackage{hybrid}
+
+\begin{document}
+
+\lstset{%
+basicstyle={\tts},basewidth={0.50em},
+numbers=none,numberstyle=\tiny,numbersep=10pt,
+aboveskip=10pt,belowskip=0pt,
+frame=single,framesep=2pt,framerule=0pt}
+
+\bgcolour{grey95}
+
+\begin{center}
+ {\Large\bf A hybrid LaTeX collection.}\\[20pt]
+ {Leo Brewin}\\[5pt]
+ {School of Mathematics, Monash University}\\[5pt]
+ {\tts Leo.Brewin@monash.edu}\\[5pt]
+ {August 2018}\\[10pt]
+ {Version 0.1}\\[10pt]
+ {\href{https://github.com/leo-brewin/hybrid-latex}{https://github.com/leo-brewin/hybrid-latex}}\\[20pt]
+ {\bf\small Abstract}\\[10pt]
+ {\small\MyPar{0.80}%
+ {This collection of LaTeX packages and Python scripts provides simple
+ tools to allow active Python to be embedded in a LaTeX document.
+ It does this by defining
+ a number of simple macros and Python scripts that build a bridge between
+ the output generated by the active code and the LaTeX code. Each language
+ is defined independently of the other languages. The scripts and macros
+ for one language are almost identical to those for the other languages in
+ the collection differing only in the names of the macros and some minor
+ language specific tweaks.
+ This makes it a simple matter to extend the collection to other languages.}}
+\end{center}
+
+\vskip 1cm
+
+\parindent=0pt
+\parskip=0pt plus 0pt minus 0pt
+
+\tableofcontents
+
+\vfill
+
+\clearpage
+
+\parindent=0pt
+\parskip=8pt plus 2pt minus 1pt
+
+\section{Introduction}
+
+Programs like Mathematica, Maple, Python and so on do a wonderful job of symbolic,
+numeric and graphical computations. On the other hand, LaTeX produces exceptional
+typeset documents but is less adept at symbolic and other forms of computation. It
+is a case of horses for courses. A common approach is to use one or more codes (in
+Python, Maple etc.) to do the computations and a separate LaTeX code to collect and
+document the results. It seems reasonable then to attempt to consolidate these
+separate codes into a single hybrid LaTeX document. That is the main purpose of
+this collection -- to provide tools that support active code within a LaTeX
+document.
+
+This document describes the CTAN version of this package. An extended version
+of the pacakge that allows inclusion of Python, Mathematica, Maple, Matlab and
+Cadabra code can be found on the
+{\href{https://github.com/leo-brewin/hybrid-latex}{GitHub repository}}.
+
+\section{The pyLaTeX package}
+
+There are other packages that do the same job, such as
+\href{https://github.com/gpoore/pythontex}{\PythonTeX} and
+\href{https://github.com/sagemath/sagetex}{\SageTeX}. In each case the journey from
+source to pdf is similar; the Python code is mined from the LaTeX source, passed
+over to Python and the output feed back into the LaTeX source. The packages differ
+in both the tools used to mine the Python code and the manner in which the output
+is made visible to the LaTeX source.
+
+In both \PythonTeX\ and \SageTeX, the Python code is mined using a first pass of
+LaTeX whereas \pyLaTeX\ uses a Python script to do the same job. There are two main
+reasons for adopting Python as the code miner. First, it is much easier to extend
+\pyLaTeX\ to incorporate other foreign languages (such as Mathematica, Matlab,
+Cadabra etc.). Doing so in \PythonTeX\ and \SageTeX\ requires careful tweaking of
+the underlying LaTeX class files -- such adventures requires a solid understanding
+of the LaTeX programming language and is not for the faint of heart. The second
+reason is that LaTeX is not the ideal tool to mine Python (or any other code) from
+a LaTeX document. There are much better text processing tools (such as Python) that
+can do the same job while being much easier (for the developer) to read, debug and
+extend.
+
+There are also some important differences in the way the end user accesses the
+Python output for use in the LaTeX source. In \PythonTeX\ and \SageTeX\ the Python
+output is saved to a collection of files (roughly one file per Python code block)
+while \pyLaTeX\ creates a single file. In all cases the contents of these files are
+made available to the LaTeX source by way of special LaTeX macros. The \PythonTeX\
+and \SageTeX\ output files are tightly coupled to the original LaTeX source. This
+means that their contents can not be easily shared with other LaTeX sources
+(without manual intervention). In contrast, the \pyLaTeX\ output is a single file
+that contains a collection of LaTeX macros, one for each piece of (tagged) Python
+output, that can be read by any other LaTeX source. Thus a user could split a
+larger LaTeX source into a collection of smaller sources (e.g., chapters of a book)
+with the Python output included as needed. An example of this sharing of Python
+output can be found in the examples directory. The file {\tts summary.tex} does no
+symbolic calculations of its own but instead pulls in selected parts of the Python
+output from other examples in that directory.
+
+Another important difference between \pyLaTeX\ and \PythonTeX\ and \SageTeX\ is
+that \pyLaTeX\ uses tags to nominate which pieces of the Python output should be
+made available to the LaTeX source. Both \PythonTeX\ and \SageTeX\ allow all Python
+output to accessed in the LaTeX source. The problem with that method is that it is
+not possible to record the history of a single Python expression. For example, if
+the Python code computes the expression {\tts foo} five times then only the fifth
+instance will be seen by LaTeX.
+
+\section{Requirements}
+
+\subsection{Latex}
+The \pyLaTeX\ package draws on a number of latex packages all of which should be
+available in any recent LaTeX distribution. The examples described in this document
+were run using the {\tts TeXLive-2018} distribution for macOS.
+
+The \pyLaTeX\ package provides both a normal style file, {\tts pylatex.sty} and a
+class file {\tts pylatex.cls}. The preamble to the style file contains the
+following declarations.
+
+\vskip 12pt
+
+\begin{latex}
+ \usepackage{comment}
+ \usepackage{listings}
+ \usepackage{keyval}
+ \usepackage{etoolbox}
+ \usepackage{xcolor}
+ \usepackage{pymacros}
+\end{latex}
+
+The {\tts pymacros} package is a key part of the \pyLaTeX\ collection as it defines
+the core macros for \pyLaTeX.
+
+The class file first includes the style file then executes the following statements
+
+\vskip 12pt
+
+\begin{latex}
+ \usepackage[papersize={297mm,210mm},
+ hmargin=2cm,tmargin=1.0cm,bmargin=1.5cm]{geometry}
+ \usepackage{amsmath}
+ \usepackage{amssymb}
+ \usepackage{hyperref}
+ \usepackage{breqn}
+\end{latex}
+
+The extra packages included in the class file are not essential but have proven
+useful in many cases and thus are included as a convenient default. Note that the
+options to the geometry package sets the output to A4 landscape format. This can be
+changed, either by editing the class file or by including a line like the following
+somewhere in the preamble of the users document.
+
+\vskip 6pt
+
+\begin{latex}
+ \geometry{margin=2.0cm,paperheight=25cm}
+\end{latex}
+
+\subsection{Python}
+There are no particular requirements on the Python environment in order to use the
+\pyLaTeX\ package though the examples listed below do require {\tts sympy} version
+1.1.1 or later. The simple measure is that if your embedded Python code can be run
+in your normal Python environment then that same code should work equally well
+using \pyLaTeX. All of the examples described in this document were run under macOS
+using the default Apple Python environment (Python 2.7) as well as under the
+Anaconda 5.2 (Python3.6) environment.
+
+\section{Setup}
+
+There is no setup tool as you only have a few files to install. The following files
+can be found inside the {\tts Python} directory of the hybrid collection.
+
+\begin{tabular}{rl}
+{\tts shell/pylatex.sh}:&Copied to anywhere that is visible on your path.\\[5pt]
+{\tts python/pypostproc.py}:&Copied to anywhere that is visible on your path.\\
+{\tts python/pypreproc.py}:&Ditto\\
+{\tts python/merge-tex.py}:&Ditto\\[5pt]
+{\tts latex/pylatex.cls}:&Copied to anywhere that is visible to LaTeX.\\
+{\tts latex/pylatex.sty}:&Ditto\\
+{\tts latex/pymacros.sty}:&Ditto
+\end{tabular}
+
+For example, the shell and Python scripts could be copied to {\tts
+\$HOME/local/sh/} while the LaTeX files could be copied to {\tts
+\$HOME/tex/inputs/}. Provided those directories are on the appropriate paths (i.e.,
+PATH and TEXINPUTS), that should be all that needs doing.
+
+Note that each of the Python scripts uses the following shebang (i.e., the first
+line in the file)
+
+\begin{lstlisting}
+#!/usr/local/bin/python3
+\end{lstlisting}
+
+You may need to change this to match the path to your version of {\tts python3}.
+
+\section{Compiling}
+To compile the file {\tts foo.tex} use
+
+\begin{lstlisting}
+ pylatex.sh -i foo
+\end{lstlisting}
+
+The {\tts pylatex.sh} script will call Pyhton and LaTeX as required to produce the
+pdf output. Along the way a number of intermediate files will be created (most of
+which will be deleted by default). Using the above command will produce not only
+the pdf but also {\tts foo.pytex}. This file contains a list of macros, one for
+each \pyLaTeX\ tag in {\tts foo.tex}, that are executed when the \pyLaTeX\ macros
+such as {\tts\verb|\py{bah}|} are called (in this case {\tts bah} is a tag
+associated with part of the Python code in the {\tts foo.tex} source). This same
+file can also be included in other LaTeX files using
+{\tts\verb|\input{foo.pytex}|}. This makes the Python output from {\tts foo.tex}
+available to other LaTeX files.
+
+Executing {\tts pylatex.sh} with the {\tts -h} flag will produce the following
+usage information.
+
+\begin{lstlisting}
+ usage : pylatex.sh -i file [-I<path to pymacros.sty>]
+ [-P<path to python>] [-s] [-k] [-x] [-h]
+ options : -i file : source file (without .tex extension)
+ -I file : full path to pymacros.sty file
+ -P path : where to find the Python binary
+ -s : silent, don't open the pdf file
+ -k : keep all temporary files
+ -x : don't call latex
+ -h : this help message
+ example : pylatex.sh -i file -P/usr/local/bin/python
+\end{lstlisting}
+
+The intermediate files produced by the {\tts -k} option are (excluding the
+standard LaTeX files)
+
+\bgroup
+\def\MYn{\vrule height 0pt depth 5pt width 0pt}
+\def\MYN{\vrule height 0pt depth 0pt width 0pt}
+\begin{tabular}{rl}
+ {\tts foo.py:}&\MyPar{0.75}%
+ {A copy of all the Python code stripped bare of (most) tags.}\\
+ {\tts foo_.py:}&\MyPar{0.75}%
+ {Similar to {\tts foo.py} but with additional Python code to catch Python
+ output for the \pyLaTeX\ tags.}\\
+ {\tts foo.pyidx:}&\MyPar{0.75}%
+ {An index of all \pyLaTeX\ tags.}\\
+ {\tts foo.pytex:}&\MyPar{0.75}%
+ {A set of macros, one for each tag, expanding to the Python output.}\\
+ {\tts foo.pytxt:}&\MyPar{0.75}%
+ {The raw Python output from {\tts foo_.py}.}
+\end{tabular}
+\egroup
+
+The {\tts -k} option is useful in cases where there is a bug in the users Python
+code. This option will force {\tts pylatex.sh} to retain all intermediate files,
+in particular the mined Python code {\tts foo.py}. This file can then be debugged
+and in turn the original LaTeX source can be corrected.
+
+The {\tts -I} option can be used in cases where the output from {\tts foo.tex} is
+intended for use in other LaTeX sources that do not use the \pyLaTeX\ style file
+{\tts pylatex.sty}. This could be useful for sharing results with colleagues who
+have not installed the \pyLaTeX\ package or when submitting a paper to a journal.
+The nett effect of the {\tts -I} option is to prepend the {\tts foo.pytex} file
+with the LaTeX definitions for all of the \pyLaTeX\ macros. Another approach would
+be to not use the {\tts -I} but share both the {\tts foo.pytex} and {\tts
+pymacros.sty} file with colleagues or journals.
+
+The only files that must be kept are {\tts foo.tex} (obviously) and {\tts
+foo.pytex}. This pair of files alone is sufficient for successful execution of
+LaTeX. The file {\tts foo.pytex} only needs to be recreated (using {\tts
+pylatex.sh}) when changes have been made to the Python code in {\tts foo.tex}.
+
+It is important to note that the Python code mined from the LaTeX source will be
+written to a single file. Thus it is important that all parts of this file
+interact harmoniously. If there is any possibility that one part of the (combined)
+code may adversely effect other parts then some action must be taken. One solution
+is to use language features of Python to avoid the clash, such as placing
+conflicting code in separate functions. Another solution is to move the
+conflicting code to separate LaTeX documents, run {\tts pylatex.sh} over each
+document, then include the results in the original LaTeX source using
+{\tts\verb|\input|} on the corresponding {\tts .pytex} files.
+
+\subsection{Caution}
+
+Be very careful -- each of the above named temporary files will overwrite any
+existing files of the same name. An easy road to disaster lies this way. Suppose
+you have an existing Python file named {\tts foo.py} and suppose you wish to catch
+its output for later use in some other LaTeX document. You might start by creating
+a wrapper file, {\tts foo.tex}, such as the following
+
+\vspace{10pt}
+
+\PySetup{action=verbatim}
+
+% note: the * in the 1st column is to ensure the python preprocessor does not respond
+% to any of the \begin{...} or \end{...} lines. The \end{document} line is the
+% real problem as it terminates the preprocessing.
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+* \documentclass[12pt]{pylatex}
+* \begin{document}
+* \begin{python}
+* \Input{foo.py}
+* \end{python}
+* \end{document}
+\end{latex}
+\egroup
+
+\PySetup{action=show}
+
+The {\tts pylatex.sh} will expand the {\tts\verb|\Input{foo.py}|} command to
+include the contents of {\tts foo.py}. No damage done -- so far. But now {\tts
+pylatex.sh} will read the newly merged file and will create its own version of
+{\tts foo.py} without \emph{any} of the \pyLaTeX\ tags. Thus any subsequent
+processing of {\tts foo.tex} will \emph{not} capture any Python output -- because
+all of the Python tags have been deleted.
+
+\subsection{The pypreproc.py and pypostproc.py scripts}
+
+The job of the {\tts pypreproc.py} script is to harvest the Python code from the
+LaTeX source. For a source named {\tt foo.tex} the script could be run using
+
+\begin{lstlisting}
+ pypreproc.py -i foo
+\end{lstlisting}
+
+This will produce {\tts foo.py, foo_.py} and {\tts foo.pyidx}. The file {\tts
+foo.py} is an almost\footnote{It may retain a few comments.} exact copy of the
+active Python code while {\tts foo_.py} is a version of {\tts foo.py} containing
+extra Python commands to catch the nominated Python output. This file is passed to
+Python to create the {\tts foo.pytxt} file which in turn is passed to {\tts
+pypostproc.py} using
+
+\begin{lstlisting}
+ pypostproc.py -i foo
+\end{lstlisting}
+
+which should create the {\tts foo.pytex} file.
+
+The pre and post processor scripts, {\tts pypreproc.py} and {\tts pypreproc.py},
+would rarely be used on their own. Though if something fails in the execution of
+the {\tts pylatex.sh} script it might prove useful to run these scripts on their
+own. Bug reports are always welcome (working on the time proven axiom that no code
+is ever bug free).
+
+\subsection{The merge-tex.py script}
+
+A common practice when writing LaTeX documents is to use a driver file to pull in
+other smaller LaTeX documents (e.g., a driver for a book could pull in the
+chapters as separate documents). Each of the chapters could contain some active
+Python code -- so how can such code be made visible to the Python preprocessor
+{\tts pypreproc.py}? That is the job of the {\tts merge-tex.py} script. It will
+read each file and copy the contents to a single merged file (named {\tts
+.merged.tex}). This file is then read by {\tts pypreproc.py}. Not all included
+files will contain active Python code so {\tts merge-tex.py} only looks for lines
+like {\tts\verb|\Input{foo.tex}|}. Other files included using {\tts\verb|\input|}
+or {\tts\verb|\include|} are ignored by {\tts merge-tex.py}. Thus the {\tts
+.merged.tex} need not be a faithful copy of the original source -- but that is not
+a problem since {\tts .merged.tex} exists solely for {\tts pypreproc.py} to
+harvest the active code after which it is no longer used.
+
+The {\tts merge-tex.py} script is language agnostic -- all it does is read its
+input and respond to any {\tts \verb|\Input|} lines. If the input file is {\tts
+foo.tex} then a merged file {\tts bah.tex} can be created using
+
+\begin{lstlisting}
+ merge-tex.py -i foo.tex -o bah.tex
+\end{lstlisting}
+
+Note that the {\tts .tex} file extensions \emph{are} required (unlike {\tts
+pypreproc.py} and {\tts pypostproc.py}).
+
+Note also that {\tts merge-tex.py} will follow nested files up to 10 deep.
+
+\section{Usage}
+
+Using \pyLaTeX\ entails the addition of user defined tags, in the form of Python
+comments, within the LaTeX source. These tags serve to connect the Python output
+to the LaTeX source. A typical example is shown in the following code.
+
+\vspace{10pt}
+
+\PySetup{action=verbatim}
+
+% Note: The * in the 1st column is to ensure the python preprocessor does not respond
+% to any of the \begin{...} or \end{...} lines. The \end{document} line is the
+% real problem as it terminates the preprocessing.
+% The * is hidden from LaTeX by way of the listinings option gobble=2.
+
+\bgroup
+\bgcolour{white}
+\latexstyle
+\begin{latex}
+* \documentclass[12pt]{pylatex}
+* \begin{document}
+* \begin{python}
+\end{latex}
+\pythonstyle
+\begin{python}
+* from sympy import *
+* x = Symbol('x')
+* ans = exp(-x) # py (ans.01,ans)
+* taylor = ans.series(x, 0, 4) # py (ans.02,taylor)
+* taylor = ans.series(x, 0, 8) # py (ans.03,taylor)
+\end{python}
+\latexstyle
+\begin{latex}
+* \end{python}
+* \begin{align*}
+* &\py*{ans.01}\\
+* &\py*{ans.02}\\
+* &\py*{ans.03}
+* \end{align*}
+* \end{document}
+\end{latex}
+\egroup
+
+\PySetup{action=show}
+
+This will lead to a pdf file that contains not just the Python output but also,
+for reference, a copy of the Python source (though this can be suppressed, see the
+section \hyperlink{sec:custom}{below} on customisation).
+
+\vspace{5pt}
+
+\begin{python}
+ from sympy import *
+ x = Symbol('x')
+ ans = exp(-x) # py (ans.01,ans)
+ taylor = ans.series(x, 0, 4) # py (ans.02,taylor)
+ taylor = ans.series(x, 0, 8) # py (ans.03,taylor)
+\end{python}
+\vspace{-10pt}
+\begin{align*}
+ &\py*{ans.01}\\
+ &\py*{ans.02}\\
+ &\py*{ans.03}
+\end{align*}
+
+The key elements to note are the \pyLaTeX\ tags (e.g., {\tts py(ans.01,ans)}) and
+the Python environment block. The tags are always part of a Python comment and are
+always of the form {\tts py(foo,bah)} where {\tts bah} is a Python symbol (or any
+printable entity) and {\tts foo} is the tag (later used in the LaTeX source). The
+\pyLaTeX\ tag can be any string of characters from the set {\tts a-zA-Z0-9.\_}. In
+the above example there are three tags, {\tts ans.01, ans.02} and {\tts ans.03}.
+The dot postfix is not essential but it provides a simple way to record a sequence
+of Python outputs. These tags are used later in the body of the LaTeX code and are
+accessed in the above example using the \pyLaTeX\ macro {\tts\verb|\py|}. This
+macro takes just one argument namely the corresponding \pyLaTeX\ tag. The macro
+{\tts\verb|\py{foo}|} will expand to the Python output for the tag {\tts foo}.
+Other macros are provided such as {\tts\verb|\py*{foo}|} which will expand to
+{\tts foo := } followed by the Python output. The full set of macros are described
+in the section \hyperlink{sec:pylatexmacros}{LaTeX macros}.
+
+The \pyLaTeX\ tags can be placed anywhere within the Python block. In the above
+example the tags were placed on the same line as the Python code. This is just for
+aesthetic effect -- they could equally well have been located on following lines.
+The \pyLaTeX\ tags should be unique within the LaTeX file. If the same tag name is
+used more than once the output associated with that tag will be from the last
+instance of that tag.
+
+Note that the {\tts pypreproc.py} script will interpret {\tts py(foo)} as a
+shorthand for {\tts py(foo,foo)}.
+
+\subsection{Undefined tags}
+
+If any of the \pyLaTeX\ macros are called for a tag that was \emph{not} defined
+then \hbox{(??)} will be printed. Note that this may cause a LaTeX syntax error
+when the \hbox{(??)} appears in an unexpected context (e.g., in cases where the
+output of {\tts\verb|\py|} was expected to expand to one or more
+{\tts\verb|\\|}'s).
+
+\subsection{Tagged blocks}
+
+There is a second form of tag, known as a tagged block, in which a block of Python
+code is enclosed in a matching {\tts\verb|# pyBeg(foo)|},
+{\tts\verb|# pyEnd(foo)|} pair. An example of a tagged block can be seen in the
+following code. The tag is given the name {\tts Pascal} and can be accessed in the
+LaTeX code using any of the \pyLaTeX\ macros, in this case {\tts\verb|\py|}. The
+intention of tagged blocks is that they can be used to capture any Python output
+generated within the tagged block (except the output that is caught by simple tags
+such as shown in the previous example).
+
+Here is a short example\footnote{This example is very \emph{inefficient} as it
+uses recursive calls for \emph{every} element in the table.} that demonstrates the
+use of a single tagged block.
+
+\vspace{10pt}
+
+\PySetup{action=verbatim}
+
+% note: the * in the 1st column is to ensure the python preprocessor does not respond
+% to any of the \begin{...} or \end{...} lines. The \end{document} line is the
+% real problem as it terminates the preprocessing.
+
+\bgroup
+\bgcolour{white}
+\latexstyle
+\begin{latex}
+* \documentclass[12pt]{pylatex}
+* \begin{document}
+*
+* \begin{python}
+\end{latex}
+\pythonstyle
+\begin{python}
+* def build(n):
+* if n==0:
+* return [1]
+* else:
+* P = build(n-1)
+* return [1] + [P[i]+P[i+1] for i in range(n-1)] + [1]
+*
+* def display(n):
+* for i in range(n):
+* ans = ""
+* for j in range(0,len(build(i))):
+* ans = ans + "\m{" + str(build(i)[j]) + "}"
+* print (ans+"\cr")
+*
+* # pyBeg (Pascal)
+* display(7)
+* # pyEnd (Pascal)
+\end{python}
+\latexstyle
+\begin{latex}
+* \end{python}
+*
+* \def\m#1{\hbox to 1cm{\hfill #1\hfill}}
+* \halign{\hbox to \textwidth{\hfill#\hfill}\cr\py{Pascal}}
+*
+* \end{document}
+\end{latex}
+\egroup
+
+\PySetup{action=hide}
+
+\begin{python}
+ def build(n):
+ if n==0:
+ return [1]
+ else:
+ P = build(n-1)
+ return [1] + [P[i]+P[i+1] for i in range(n-1)] + [1]
+
+ def display(n):
+ for i in range(n):
+ ans = ""
+ for j in range(0,len(build(i))):
+ ans = ans + "\m{" + str(build(i)[j]) + "}"
+ print (ans+"\cr")
+
+ # pyBeg (Pascal)
+ display(7)
+ # pyEnd (Pascal)
+\end{python}
+
+\clearpage
+
+\PySetup{action=show}
+
+The output of the above code (excluding the echoed Python code) is Pascal's triangle (as expected).
+
+\def\m#1{\hbox to 1cm{\hfill #1\hfill}}
+\halign{\hbox to \textwidth{\hfill#\hfill}\cr\py{Pascal}}
+
+All Python code must be contained within the Python environment block, i.e.,
+within a {\tts\verb|\begin{python}|} {\tts\verb|...|} {\tts\verb|\end{python}|}
+pair. There is no facility to allow \emph{inline} execution of Python code (though
+this is allowed in other packages, notably \PythonTeX). The reason for taking this
+approach was to force a clear separation between native LaTex code and active
+Python blocks. This makes it easier to locate the Python code. If an inline
+calculation is needed then it is a simple matter of including the Python code in a
+Python block and using a tag to catch and display the result.
+
+Tagged blocks can be nested (though it is not clear what use this might serve) and
+they can contain simple tags. The simple tags will always take priority over
+tagged blocks in capturing Python output. Tagged blocks should respect the usual
+rules of begin-end blocks -- they can nested but they must not overlap. The Python
+pre and post processors (within the {\tts pylatex.sh} script) will report errors
+when tagged blocks are not properly structured (i.e., overlapping, unmatched {\tts
+pyBeg/pyEnd} items etc.).
+
+\subsection{LaTeX macros}
+\hypertarget{sec:pylatexmacros}{}
+
+The \pyLaTeX\ package provides a number commands for typesetting tagged expressions.
+
+\newbox\Slashpya
+\setbox\Slashpya=\hbox{\tts\verb|\py{foo}|}
+
+\newbox\Slashpyb
+\setbox\Slashpyb=\hbox{\tts\verb|\py*{foo}|}
+
+\newbox\SlashPya
+\setbox\SlashPya=\hbox{\tts\verb|\Py{foo}|}
+
+\newbox\SlashPyb
+\setbox\SlashPyb=\hbox{\tts\verb|\Py*[bah]{foo}|}
+
+\newbox\Slashhfill
+\setbox\Slashhfill=\hbox{\tts\verb|[\hfill]|}
+
+\newbox\SlashPySetup
+\setbox\SlashPySetup=\hbox{\tts\verb|\PySetup{key=value}|}
+
+\newbox\SlashDmatha
+\setbox\SlashDmatha=\hbox{\tts\verb|\Dmath[bah]{foo}|}
+
+\newbox\SlashDmathb
+\setbox\SlashDmathb=\hbox{\tts\verb|\Dmath*[bah]{foo}|}
+
+\newbox\SlashttTag
+\setbox\SlashttTag=\hbox{\tts\verb|\ttTag{foo}|}
+
+\newbox\SlashInput
+\setbox\SlashInput=\hbox{\tts\verb|\Input{foo.tex}|}
+
+\begin{longtable}{rl}
+ {\copy\Slashpya}&\MyPar{0.70}{%
+ Display the value of {\tts foo} without any additional decorations.}\\
+ {\copy\Slashpyb}&\MyPar{0.70}{%
+ Similar to \copy\Slashpya\ but adds {\tts foo$\colonEq$}
+ immediately to the left of {\tts foo}.}\\
+ {\copy\SlashPya}&\MyPar{0.70}{%
+ Display the value of {\tts foo} and set the equation tag to be ({\tts
+ foo}). Since this macro creates its own equation tag it should not be used
+ in any maths environment that also creates an equation tag (e.g., {\tts
+ align, equation} etc.) It can not be used in any of the {\tts breqn}
+ environments ({\tts breqn} will report a package error).}\\
+ {\copy\SlashPyb}&\MyPar{0.70}{%
+ Use this version of \copy\SlashPya\ in any of the (starred) {\tts breqn}
+ environments. The optional argument {\tts [bah]} specifies the spacing
+ between the end of {\tts foo} and the right hand edge of the tag. The
+ default is \copy\Slashhfill\ which forces the tag to the far right.}\\
+ {\copy\SlashDmatha}&\MyPar{0.70}{%
+ This is a shortcut for the {\tts dmath} environment. The optional and
+ required arguments of \copy\SlashDmatha\ are passed onto the {\tts dmath}
+ environment. See page (\pageref{ex:Dmath}) for an example.}\\
+ {\copy\SlashDmathb}&\MyPar{0.70}{%
+ This is similar to \copy\SlashDmatha\ but with the one small change that it
+ applies to the {\tts dmath*} environment.}\\
+ {\copy\SlashttTag}&\MyPar{0.70}{%
+ This is a simple macro that typesets a tag name such as {\tts foo} in a
+ small typewriter font enclosed in matching parenthesis, e.g., ({\tts
+ foo}).}\\
+ {\copy\SlashPySetup}&\MyPar{0.70}{%
+ This command takes one argument in the form of a key=value pair. Its
+ purpose is to set global options for the following Python blocks. The
+ current list of options is limited to one key with three values. These are
+ described in the following section.}\\
+\end{longtable}
+
+\subsection{Custom formats}
+\hypertarget{sec:custom}{}
+
+The \pyLaTeX\ package allows for some minor customisation of the formatting of the Python code. The macro
+{\tts\verb|\PySetup|} can be used to set the preferred options using key-value pairs. There is only
+one key as described in the following table.
+
+\begin{tabular}{rl}
+ {\tts action=show}&%
+ \MyPar{0.70}{Make the Python code visible and active (i.e., cancel the
+ {\tts hide} and {\tts verbatim} actions).}\\
+ {\tts action=hide}&%
+ \MyPar{0.70}{Hide the python code but still allow the Python code to be
+ active.}\\
+ {\tts action=verbatim}&%
+ \MyPar{0.70}{This will make the Python code inactive (i.e., it will not
+ be passed to Python).}\\[5pt]
+\end{tabular}
+
+Multiple calls to {\tts\verb|\PySetup|} can be made and apply to all subsequent
+Python environments or until changed by a later call to {\tts\verb|\PySetup|}. The
+default value is {\tts action=show}.
+
+The \pyLaTeX\ package uses the {\tts listings} package which allows further
+formatting changes to be made. For example, to add line numbers and a shaded
+background to the Python code use
+
+\begin{lstlisting}
+ \lstset{numbers=left,backgroundcolor=\color{lightgrey}}
+\end{lstlisting}
+
+Many other options are available, see the {\tts listings} documentation for full
+details.
+
+\subsection{Python indentation}
+
+Python has very strict (but simple) indentation rules that must be observed not
+only within a single Python block but across all Python blocks. Why? Because all
+of the Python blocks will be collected into a separate single Python code and that
+code must observe the Python indentation rules.
+
+\subsection{Error reporting}
+
+None of the packages in this collection treat errors from the active code with any
+degree of aplomb -- at best they report that an error occurred, at worst they
+silently ignore the error leaving {\tts pdflatex} to pick up the pieces. This is
+far from ideal. If in doubt, run the main script (e.g., {\tts pylatex.sh}) using
+the {\tts -k -x} command line options then inspect the file {\tts foo.pytxt} for
+any errors. If there are errors then you can debug the extracted code {\tts
+foo.py} later returning the corrected code back to the LaTeX source {\tts foo.tex}.
+
+\subsection{Matplotlib and macOS}
+
+There is a well known issue when using Matplotlib on macOS where some Matplotlib
+codes may fail. The
+\href{https://matplotlib.org/faq/osx_framework.html}{Matplotlib documentation}
+provides a number of suggestions including to use {\tts pythonw} rather than {\tts
+python}. For such cases use the {\tts -P} flag to set the path to the {\tts
+pythonw} command when invoking the {\tts pylatex.sh}. This has been tried and
+tested under the Anaconda Python3 environment for macOS.
+
+\section{Examples}
+
+The {\tts examples} directory contains a small collection of complete \pyLaTeX\
+codes that showcase the various features of the \pyLaTeX\ package. The Python
+source contains inline comments that result in long lines of text that do not
+comfortably fit on an A4 page in portrait mode. Thus most of the examples have
+been formatted in A4 landscape mode (this is the default setting for the \pyLaTeX\
+class). Consequently it is not practical to include those examples in this file.
+The following table provides a very brief summary of each example (with hyperlinks
+to the corresponding pdf's in {\tts ../python/examples/}).
+
+\newbox\exa
+\setbox\exa=\hbox{\href{../python/examples/example-01.pdf}{Example 1}}
+
+\newbox\exb
+\setbox\exb=\hbox{\href{../python/examples/example-02.pdf}{Example 2}}
+
+\newbox\exc
+\setbox\exc=\hbox{\href{../python/examples/example-03.pdf}{Example 3}}
+
+\newbox\exd
+\setbox\exd=\hbox{\href{../python/examples/example-04.pdf}{Example 4}}
+
+\newbox\exe
+\setbox\exe=\hbox{\href{../python/examples/example-05.pdf}{Example 5}}
+
+\newbox\exf
+\setbox\exf=\hbox{\href{../python/examples/example-06.pdf}{Example 6}}
+
+\newbox\exg
+\setbox\exg=\hbox{\href{../python/examples/example-07.pdf}{Example 7}}
+
+\newbox\exh
+\setbox\exh=\hbox{\href{../python/examples/example-08.pdf}{Example 8}}
+
+\newbox\exi
+\setbox\exi=\hbox{\href{../python/examples/example-09.pdf}{Example 9}}
+
+\newbox\exz
+\setbox\exz=\hbox{\href{../python/examples/summary.pdf}{Summary}}
+
+\begin{longtable}{rl}
+ \box\exa:&\MyPar{0.80}%
+ {This is a collection of basic mathematical computations. It contains
+ examples of simple tags and tagged blocks.}\\
+ \box\exb:&\MyPar{0.80}%
+ {This is the first of two examples drawn from the \PythonTeX\ website
+ \href{https://github.com/gpoore/pythontex/}{(here)}. It shows a nice example
+ of using a tagged block.}\\
+ \box\exc:&\MyPar{0.80}%
+ {This is the second example taken from the \PythonTeX\ website
+ \href{https://github.com/gpoore/pythontex/}{(here)}. It shows a step-by-step
+ computation of a simple triple integral.}\\
+ \box\exd:&\MyPar{0.80}%
+ {This example shows how {\tts Matplotlib} and friends can be used to
+ construct a simple xy-plot.}\\
+ \box\exe:&\MyPar{0.80}%
+ {This example shows how problems with the placement of equation tags can be
+ resolved by careful choice of the optional argument to
+ {\copy\SlashPyStar}.}\\
+ \box\exf:&\MyPar{0.80}%
+ {This is a simple example that uses Python to compute the first few
+ iterations of a Newton-Raphson method.}\\
+ \box\exg:&\MyPar{0.80}%
+ {This example contains a single tag-block. It captures basic system data.}\\
+ \box\exh:&\MyPar{0.80}%
+ {This example shows how to completely hide the Python code as well a trick
+ for hiding just the tags.}\\
+ \box\exi:&\MyPar{0.80}%
+ {This example is a proof of concept example. It shows one approach for
+ passing LaTeX information to the Python code. The code is not elegant but it
+ does the job.}\\
+ \box\exz:&\MyPar{0.80}%
+ {There is no Python code in this example. Instead, the results from the
+ above examples are included by inputting the corresponding {\tts .pytex}
+ file.}
+\end{longtable}
+
+\section{Splitting long lines using breqn}
+
+On some occasions the output from a computation may be too long to fit comfortably
+on one line. In such cases some form of line splitting is required. A less than
+ideal approach is to manually edit the output by inserting carefully chosen line
+breaks. Not only is this approach tedious and inelegant it also requires the line
+breaks to be reset whenever the document format is changed (e.g., from A4 to
+letter size) or when some of the computations are changed (e.g., showing twice as
+many terms in a series expansion).
+
+A better approach is to use the {\tts breqn} package which uses sophisticated
+algorithms to find good line breaks with minimal input from the user. In many
+cases {\tts breqn} will produce an acceptable output. But it is not without its
+own limitations\footnote{The {\tts breqn} documentation does note that it is a
+work in progress.} as some of the following examples will demonstrate. The fact is
+that there are no algorithms that will guarantee prefect line splitting as there
+will always be some subjective element in what constitutes a good line break. The
+following series of examples are intended as guide of what to expect when using
+{\tts breqn} and also to demonstrate some possible remedies.
+
+Here is a simple example based on a truncated Taylor series expansion of $1/(1+x)$
+around $x=0$.
+\bgroup
+\lstset{gobble=2,numbers=left}
+\begin{python}
+ from sympy import *
+ x = Symbol('x')
+ ans = 1/(1+x) # py (fun,ans)
+ taylor = ans.series(x, 0, 6) # py (ans.101,taylor)
+ taylor = ans.series(x, 0, 9) # py (ans.102,taylor)
+ taylor = ans.series(x, 0, 12) # py (ans.103,taylor)
+ taylor = ans.series(x, 0, 15) # py (ans.104,taylor)
+ taylor = ans.series(x, 0, 30) # py (ans.105,taylor)
+\end{python}
+\egroup
+For an expansion with only a handful of terms the usual {\tts align} environment
+produces an acceptable output as demonstrated in the following code and output.
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \begin{align*}
+ \py{fun} &= \py {ans.101}\tag{\ttTag{ans.101}}\\
+ &= \py {ans.102}\tag{\ttTag{ans.102}}\\
+ &= \py {ans.103}\tag{\ttTag{ans.103}}
+ \end{align*}
+\end{latex}
+\egroup
+\begin{align*}
+ \py{fun} &= \py {ans.101}\tag{\ttTag{ans.101}}\\
+ &= \py {ans.102}\tag{\ttTag{ans.102}}\\
+ &= \py {ans.103}\tag{\ttTag{ans.103}}
+\end{align*}
+In this and the following examples the equation tags have been explicitly matched
+to the corresponding {\tts sympy} expressions. This makes it somewhat easier to
+follow the progress of a computation. The normal equation numbering (e.g., (1),
+(2) etc.) can be recovered by deleting the calls to {\tts\verb!\tag{...}!}. The
+{\tts\verb|\ttTag|} macro, defined in the \pyLaTeX\ package, does as its name
+suggests -- typesets the tag in the {\tts\verb|\tt|} font.
+
+The above works well for short expressions but for longer expressions it is much
+better to use the {\tts breqn} package. The key points to note in the following
+example are the use of the {\tts dmath} environment and the manner in which the
+equation tags have been set.
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \usepackage{breqn}
+ ...
+ \begin{dmath}[number={\ttTag{ans.105}}]
+ \py {fun} = \py {ans.105}
+ \end{dmath}
+\end{latex}
+\egroup
+The corresponding output is
+\Dmath[number={\ttTag{ans.105}}]{\py{fun} = \py{ans.105}}
+
+The {\tts dmath} environment is one of a number environments provided by the {\tts
+breqn} package. Its job is to chose sensible line breaks that produce a pleasant
+output (though what constitutes \emph{pleasant} may be up for debate). Note that
+all of the {\tts breqn} environments do \emph{not} support the {\tts\verb!\tag!}
+macro for setting equation tags. The only way to do so is through the
+{\tts\verb!number={...}!} optional argument as shown in the above example. To
+suppress the equation label use the {\tts dmath*} environment.
+
+\bgroup
+\advance\leftskip1cm
+\advance\rightskip1cm
+\hypertarget{landing}{{\bf Note:}}
+This sentence may seem out of place but its purpose is to demonstrate a claim made
+later is this documentation that, with a suitably modified label macro, the {\tts
+hyperref} package can be used to jump to the correct page when clicking on a
+hyperlink for an equation. For example, clicking on this link \eqref{eq:target}
+should take us to page \pageref{eq:target}. But now, back to the main discussion.
+\par
+\egroup
+
+The {\tts breqn} package also provides a {\tts dgroup} environment. This can be
+used to group a sequence of {\tts dmath} environments to align the output on a
+targeted symbol (usually the first equals sign). Here is a short example
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\lstlatex{numbers=left}
+\begin{latex}
+ \begin{dgroup}
+ \begin{dmath}[number={\ttTag{ans.103}}] \py {fun} = \py {ans.103} \end{dmath}
+ \begin{dmath}[number={\ttTag{ans.104}}] {} = \py {ans.104} \end{dmath}
+ \begin{dmath}[number={\ttTag{ans.105}}] {} = \py {ans.105} \end{dmath}
+ \end{dgroup}
+\end{latex}
+\egroup
+
+and here is the corresponding output
+\begin{dgroup}
+ \begin{dmath}[number={\ttTag{ans.103}}] \py {fun} = \py {ans.103} \end{dmath}
+ \begin{dmath}[number={\ttTag{ans.104}}] {} = \py {ans.104} \end{dmath}
+ \begin{dmath}[number={\ttTag{ans.105}}] {} = \py {ans.105} \end{dmath}
+\end{dgroup}
+
+There are a few points to be made here. First is the less then ideal placement of
+tags. Second is the somewhat ungainly syntax. Both of these points will be
+discussed in more detail shortly. Next, notice the {\tts\verb!{}!} preceding the
+equal signs in lines 3 and 4. This supplies an empty left hand side for each
+equation and is essential to ensure proper alignment (on the equals sign) across
+all three equations. Unlike other maths environments, {\tts breqn} does not allow
+you to specify which symbol to use as the alignment target -- that choice is made
+deep within the inner workings of {\tts dmath} and friends. It will choose symbols
+including {\tts\verb!=-+:()!}. If you wish to tell {\tts dmath} to not use a
+particular symbol you can wrap that symbol inside {\tts\verb!\hiderel!} as in the
+following example.
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \begin{dgroup*}
+ \begin{dmath*} f(x) \hiderel{=} \py {fun} = \py {ans.101} \end{dmath*}
+ \begin{dmath*} {} = \py {ans.102} \end{dmath*}
+ \end{dgroup*}
+\end{latex}
+\egroup
+\begin{dgroup*}
+ \begin{dmath*} f(x) \hiderel{=} \py {fun} = \Py*{ans.101} \end{dmath*}
+ \begin{dmath*} {} = \Py*{ans.102} \end{dmath*}
+\end{dgroup*}
+
+Consider now the earlier example in which the equation tags were not well placed
+and where the syntax was described as ungainly. The syntax can be tidied slightly
+using one of the features of the {\tts breqn} package -- it allows the {\tts
+dmath} and {\tts dmath*} environments to be wrapped in user defined macros such as
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \newcommand*{\Dmath}[2][]{\begin{dmath}[#1]#2\end{dmath}}
+\end{latex}
+\egroup
+This defines {\tts\verb!\Dmath!} as a macro that takes one required argument and
+one optional argument (both of which are passed on to {\tts dmath}). It is not a
+huge saving but even so it does save a few keystrokes. Here is one of the previous
+examples rewritten using {\tts\verb!\Dmath!}.
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \begin{dgroup}
+ \Dmath[number={\ttTag{ans.103}}]{ \py {fun} = \py {ans.103} }
+ \Dmath[number={\ttTag{ans.104}}]{ {} = \py {ans.104} }
+ \Dmath[number={\ttTag{ans.105}}]{ {} = \py {ans.105} }
+ \end{dgroup}
+\end{latex}
+\egroup
+The \pyLaTeX\ package defines {\tts\verb|\Dmath|} for the {\tts dmath} environment
+as well as {\tts\verb|\Dmath*|} as a shortcut for the {\tts dmath*} environment.
+
+The use of {\tts\verb|\Dmath*|} does save some keystrokes but it does not fix the
+problem where the text is obscured by the tag. There seems to be no simple way to
+tell {\tts breqn} to avoid such problems while retaining {\tts breqn}'s method of
+placing the tags. The {\tts\verb|\Py*|} macro avoids this problem by presenting
+{\tts dmath*} with a concatenated string built from the text (e.g., the output of
+{\tts\verb|\py{foo}|}), some flexible white space (usually {\tts\verb|\hfill|})
+and the tag (e.g., {\tts foo}). This string is processed by {\tts dmath*} and line
+splits are inserted at its discretion. This will guarantee that the all of the
+text and the tag will be displayed. The user defined whitespace can always be
+chosen so that the tag does not overlap the text. This is a bare minimum of what
+could be deemed an acceptable output -- non overlap of the text and the tag. The
+output might not be optimal but at least it is readable. Here is the same example
+as above but this time using {\tts\verb|\Py*|} to display the text and the tags.
+
+\vskip 12pt
+
+\pglabel{ex:Dmath}
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \begin{dgroup*}
+ \Dmath*{ \py {fun} = \Py* {ans.103} }
+ \Dmath*{ {} = \Py*[\hskip 2cm] {ans.104} }
+ \Dmath*{ {} = \Py*[\hskip 3cm] {ans.105} }
+ \end{dgroup*}
+\end{latex}
+\egroup
+\begin{dgroup*}
+ \Dmath*{ \py {fun} = \Py* {ans.103} }
+ \Dmath*{ {} = \Py*[\hskip 2cm] {ans.104} }
+ \Dmath*{ {} = \Py*[\hskip 3cm] {ans.105} }
+\end{dgroup*}
+The whitespace between the text and the tag is passed through the optional
+argument of {\tts\verb|\Py*|} with the default set as {\tts\verb|\hfill|}. The
+inner workings of {\tts\verb|\Py*|} sets the tag using {\tts\verb|\llap|} and thus
+the whitespace optional argument measures the space between the right hand edge of
+the tag and left hand end of the equation text. Note also that this example uses
+the starred version of {\tts dgroup} and {\tts\verb|\Dmath*|}. This is to ensure
+that {\tts breqn} plays no part in forming the tag (as that is handled by
+{\tts\verb|\Py*|}).
+
+The \pyLaTeX\ package defines both {\tts\verb|\Py|} and {\tts\verb|\Py*|}. The
+{\tts\verb|\Py|} macro is intended for use only in the starred maths environments
+(e.g., {\tts align*, equation*} etc.). Like {\tts\verb|\Py*|}, it also sets the
+equation tag to match the expression but it does so using standard methods
+(internally it calls {\tts\verb|\tag|}). This last point (that {\tts\verb|\Py*|}
+uses {\tts\verb|\tag|}) also means that it can not be used in any of the {\tts
+breqn} environments (doing so will cause LaTeX to issue a {\tts breqn} package
+error).
+
+Both {\tts\verb|\Py|} and {\tts\verb|\Py*|} support the usual method of labelling
+and referencing equations using {\tts\verb|\label{foo}|} and
+{\tts\verb|\ref{foo}|}. However, there are good reasons to use a modified version
+of the {\tts\verb|\label|} macro (as described below) to improve the accuracy of
+the label-reference pairs when using hyperlinks (i.e., so that the reference
+points to the correct page where the label was issued).
+
+\subsection{Hyperref, hyperlinks and breqn}
+
+The {\tts breqn} package does support the {\tts hyperref} package though as
+discussed
+\href{https://tex.stackexchange.com/questions/193380/hyperref-pageref-links-point-t
+o-first-page}{(here)} the hyperlinks to an equation may not work as expected
+(clicking on a link may take you to the wrong page). The suggested fix is to
+define equation labels via a modified label macro such as the following
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \newcommand{\pglabel}[1]{\phantomsection\label{#1}}
+\end{latex}
+\egroup
+An example of its use might be
+
+\vskip 12pt
+
+\bgroup
+\bgcolour{white}
+\begin{latex}
+ \begin{dmath}[number={\ttTag{ans.105}}]
+ \py{fun} = \py{ans.105} \pglabel{eq:target}
+ \end{dmath}
+\end{latex}
+\egroup
+\begin{dmath}[number={\ttTag{ans.105}}]
+ \py{fun} = \py{ans.105} \pglabel{eq:target}
+\end{dmath}
+Then clicking on the link defined by {\tts\verb!\ref{eq:target}!} will bring the
+reader to this page. An example of such a link was seen earlier in this document
+(click \hyperlink{landing}{here} to jump back to that page).
+
+\section{Licence}
+
+This software is licensed under the MIT License (MIT). Please see the {\tts
+LICENCE.txt} file for more information.
+
+\section{Version history}
+\leftline{\bf v0.1 (2018/08/22)}% 22 Aug 2018
+\begin{itemize}
+\item Initial public release.
+\end{itemize}
+
+\end{document}