summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/robust-externalize/robust-externalize.tex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/robust-externalize/robust-externalize.tex')
-rw-r--r--macros/latex/contrib/robust-externalize/robust-externalize.tex903
1 files changed, 847 insertions, 56 deletions
diff --git a/macros/latex/contrib/robust-externalize/robust-externalize.tex b/macros/latex/contrib/robust-externalize/robust-externalize.tex
index 58d64342c5..f06333b9fe 100644
--- a/macros/latex/contrib/robust-externalize/robust-externalize.tex
+++ b/macros/latex/contrib/robust-externalize/robust-externalize.tex
@@ -1,3 +1,4 @@
+%\pdfoutput=1% Do not remove, needed for arxiv
\documentclass[a4paper,doc2]{ltxdoc} % doc2 is needed to force the old version, or links get colored in a weird red way even with hidelinks. https://github.com/latex3/latex2e/issues/822
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -10,15 +11,24 @@
\usepackage{amsmath}
\usepackage[margin=3cm]{geometry}
\usepackage{calc}
+\usepackage{siunitx}
\usepackage{tikz}
+\usepackage{tikzit}
+\input{new_zxstyle.tikzstyles}
\usetikzlibrary{shadows,fit}
% \usetikzlibrary fails because file is not in current directory, lazy to setup TEXINPUTS
\makeatletter
\usepackage{robust-externalize}
\makeatother
\robExtConfigure{
- enable optimizations
-}
+ enable optimizations,
+ copy file to cache={zx-calculus.sty},
+ copy file to cache={tikzlibraryzx-calculus.code.tex},
+ % You need to uncomment that line to rename the .tex files into .tex-backup
+ % backup source for arxiv,
+ rename backup files for arxiv,
+ print source when saving, % debug
+}
\usepackage{zx-calculus}
\usepackage{forest}
\setlength{\marginparwidth}{2cm}
@@ -26,6 +36,7 @@
% Loads the great package that produces tikz-like manual (see also tikzcd for examples)
\input{pgfmanual-en-macros.tex} % Is supposed to be included in recent TeX distributions, but I get errors...
+\usepackage{gnuplot-lua-tikz} %% Generate with gnuplot -e "set terminal tikz createstyle"
%% For verbatim environments:
@@ -94,7 +105,7 @@
{\Large\bfseries Cache anything (\tikzname, tikz-cd, python…),\\in a robust, efficient and pure way.}
\vspace{1em}
- {Léo Colisson \quad Version 2.2}\\[3mm]
+ {Léo Colisson \quad Version 2.5}\\[3mm]
{\href{https://github.com/leo-colisson/robust-externalize}{\texttt{github.com/leo-colisson/robust-externalize}}}
\end{center}
@@ -102,10 +113,11 @@
\bigskip
-\textbf{WARNING: This library is young and might lack some testing (and is an important rewrite of a previous version), but v2.0 is definitely usable. Even if we try to stay backward compatible, the only guaranteed way to be immune to changes is to copy/paste the library in your main project folder. Please report any bug to \url{https://github.com/leo-colisson/robust-externalize}!}
+\textbf{WARNING: Even if we try to stay backward compatible, the only guaranteed way to be 100\% immune to changes is to copy/paste the\ .sty file of the library in your main project folder. Please report any bug to \url{https://github.com/leo-colisson/robust-externalize}!}
-\textbf{WARNING 2: the coming version 2.1 improves significantly the compilation time compared with 2.0 that was surprisingly slow. Now, it is fairly well optimized (but the code needs a bit of cleaning and documentation before doing an official release)}
+\textbf{WARNING 2: the recent versions 2.1 and 2.2 improves significantly the compilation time compared with 2.0 that was surprisingly slow. Now, it is fairly well optimized, and version 2.3 is even more optimized.}
+\textbf{WARNING 3: If you read this documentation from the arXiv or CTAN, you might prefer to read it from \mylink{https://github.com/leo-colisson/robust-externalize}{Github} to get the latest version.}
\section{A taste of this library}
@@ -118,7 +130,7 @@ This library allows you to cache any language: not only \LaTeX{} documents and \
enable fallback to manual mode,
}
\end{verbatim}
-Then type something like this (note the |C| for |cached| at the end of |tikzpictureC|, see below to override the original command), and compile with |pdflatex -shell-escape yourfile.tex| (or \textcolor{red}{\textbf{read below if you do not want to use }}|-shell-escape|\textcolor{red}{\textbf{ (note that overleaf enables shell-escape by default, and it not needed once all pictures are cached)}}):
+Then type something like this (note the |C| for |cached| at the end of |tikzpictureC|, see below to override the original tikz commands), and compile with |pdflatex -shell-escape yourfile.tex| (or \textcolor{red}{\textbf{read below if you do not want to use }}|-shell-escape|\textcolor{red}{\textbf{ (note that overleaf enables shell-escape by default, and it is not needed once all pictures are cached)}}):
\begin{codeexample}[width=0pt,vbox]
\robExtConfigure{
add to preset={tikz}{
@@ -128,11 +140,16 @@ Then type something like this (note the |C| for |cached| at the end of |tikzpict
}
The next picture is cached %
\begin{tikzpictureC}[baseline=(A.base)]
- \node[fill=red, rounded corners](A){My node that respects baseline \ding{164}.};
+ \node[fill=red, rounded corners](A){My node respecting baseline \ding{164}.};
\node[fill=red, rounded corners, opacity=.3,overlay] at (A.north east){I am an overlay text};
\end{tikzpictureC} and you can see that overlay and depth works.
\end{codeexample}
+Since v2.3 we also provide a way to include online pictures with |\includegraphicsWeb|:
+\begin{codeexample}[width=0pt,vbox]
+Here is a picture of cat downloaded online: \includegraphicsWeb[width=3cm]{http://placekitten.com/400/300}.
+\end{codeexample}
+
You can also cache arbitrary code (e.g.\ python). You can also define arbitrary compilation commands, inclusion commands, and presets to fit you need. For instance, you can create a preset to obtain:
\begin{codeAndResult}
@@ -145,7 +162,7 @@ for name in ["Alice", "Bob"]:
Actually, we also provide this style by default (and explain how to write it yourself), just make sure to load:
\begin{verbatim}
\usepackage{pythonhighlight}
-\usepackage{tcolorbox}
+\usepackage[most]{tcolorbox}
\end{verbatim}
You can also cache any environment and command using something like:
@@ -208,6 +225,17 @@ A ZX figure %
}
\end{codeAndResult}
\end{itemize}
+
+We also provide methods to cache automatically \mylink{https://tikzit.github.io/}{TikZit} pictures (|\cacheCommand| alone would not be sufficient as the source relies on an external file):
+
+\begin{codeexample}[vbox]
+ %%%%%%% In your preamble:
+ \cacheTikzitWithStyle{new_zxstyle.tikzstyles}
+
+ %%%%%%% In your document:
+ \tikzfig{demo} %figures/ can be omitted
+\end{codeexample}
+
You can also cache all tikz pictures by default, except those that are run from some commands (as remember picture does not work yet, this is important). For instance, this code will allow you to freely use the |todonotes| package (that uses internally tikz but is not cachable with this library since it uses remember picture) while caching all other elements:
\begin{codeexample}[code only]
%% this will cache \tikz and tikzpictures by default (using the tikz preset)
@@ -341,6 +369,13 @@ We also provide a number of other functionalities, among others:
\item And more\dots
\end{itemize}
+\section{Acknowledgments}
+
+I am deeply indebted to many users on \url{tex.stackexchange.com} that made the writing of this library possible. I can't list you all, but thank you so much! A big thanks also to the project \url{https://github.com/sasozivanovic/memoize/} from which I borrowed most of the code to automatically wrap commands. Thanks to kiryph and dflvunoooooo for providing very useful feedbacks.
+
+\section{Support}
+
+If you find this library useful, please consider citing the arXiv version of this documentation, possibly using |\nocite|. If you want to support me financially and offer me a virtual coffee, you can use my \mylink{https://github.com/sponsors/tobiasBora}{GitHub sponsor page}.
\section{Introduction}
@@ -378,10 +413,10 @@ I tested the library on Linux and Windows, but the library should work on all OS
\paragraph{Do I need to compile using -shell-escape?}
-Since we need to compile the images via an external command, the simpler option is to add the argument |-shell-escape| to let the library run the compilation command automatically (this is also the case of \tikzname's externalize library). However, people worried by security issues of |-shell-escape| (that allows arbitrary code execution if you don't trust the \LaTeX{} code) might be interested by these facts:
+Since we need to compile the images via an external command the first time, the simpler option is to add the argument |-shell-escape| to let the library run the compilation command automatically (this is also the case of \tikzname's externalize library). Note that overleaf already defines this option by default, so you don't need to do anything special in overleaf. Moreover, this is only needed \textbf{during the first compilation} since once the image is cached, |-shell-escape| is not needed anymore (therefore, on the arXiv website, you can upload the |robustExternalize| folder containing the cached images without any issue, see \cref{sec:arxiv} for details). However, people worried by security issues of |-shell-escape| (that allows arbitrary code execution if you don't trust the \LaTeX{} code) might be interested by these facts:
\begin{itemize}
-\item You can choose to display a dummy content explaining how to manually compile the pictures until they are compiled, see |enable fallback to manual mode|.
-\item You can compile manually the images: all the commands that are left to be executed are also listed in \texttt{robExt-compile-missing-figures.sh} and you can just inspect and run them, either with \texttt{bash robExt-compile-missing-figures.sh} or by typing them manually (most of the time it's only a matter of running \texttt{pdflatex somefile.tex}).
+\item You can choose to display a dummy content explaining how to manually compile the pictures instead of giving an error until they are compiled, see |enable fallback to manual mode|.
+\item You can compile manually the images: all the commands that are left to be executed are also listed in \texttt{JOBNAME-robExt-compile-missing-figures.sh} and you can just inspect and run them, either with \texttt{bash robExt-compile-missing-figures.sh} or by typing them manually (most of the time it's only a matter of running \texttt{pdflatex somefile.tex} from the \texttt{robustExternalize} folder).
\item If you allowed:
\begin{itemize}
\item |pdflatex| (needed to compile latex documents)
@@ -396,11 +431,29 @@ Since we need to compile the images via an external command, the simpler option
\paragraph{Is it working on overleaf?}
-Yes: overleaf automatically compiles documents with |-shell-escape|, so nothing special needs to be done there (of course, if you use this library to run some code, the programming language might not be available, but I heard that python is installed on overleaf servers for instance, even if this needs to be doubled checked). If the first compilation of the document to cache images times out, you can just repeat this operation multiple times until all images are cached.
+Yes: overleaf automatically compiles documents with |-shell-escape|, so nothing special needs to be done there (of course, if you use this library to run some code, the programming language might not be available, but I heard that python is installed on overleaf servers for instance, even if this needs to be doubled checked). If the first compilation of the document to cache images times out, you can just repeat this operation multiple times until all images are cached. In case of doubt, you can look at the log file to see which file is getting cached. If overleaf still times out, read the next paragraph.
+
+\paragraph{Overleaf still times-out, why?}
+
+During the first compilation, the pictures are not compiled, so you may obtain a time out. However, at each compilation, new pictures should be added to the cache, so you should eventually be able to compile (check the log file, you should read ``No need to recompile XX.pdf'' if the picture is already in the cache). If you want this to be faster, you can try to enable |\robExtConfigure{compile in parallel}| in order to compile the pictures in parallel (need 2 compilations). If you do not often change all pictures, you can also locally download the project (it might be more practical to use the git bridge if you have it enabled), compile them locally, and copy back the |robustExternalize| folder containing all cached pictures.
+
+If all pictures are still compiled, but you still experience timeouts, you can try to use compiled presets, with something like:
+\begin{verbatim}
+\robExtConfigure{
+ new compiled preset={compiled ZX}{templateZX, compile latex template}{}
+}
+\end{verbatim}
+to create a new, more efficient (we call it compiled) preset called |compiled ZX| from a preset |templateZX|.
+
+You can also try to reduce the compilation time by reducing the number of compilation passes. Indeed, overleaf will run |pdflatex| multiple times to make it converge to the final version, increasing mechanically the compilation time (for instance a file that takes 6s to compile locally was not able to compile online). You can force overleaf to compile a single time the document by creating a |latexmkrc| file at the root of the project, containing:
+\begin{verbatim}
+$max_repeat=1
+\end{verbatim}
+Of course, you might need to recompile more than once the document to reach the final version.
\paragraph{Do you have some benchmarks?}
-We completely rewrote the \href{https://github.com/leo-colisson/robust-externalize/commit/09a05a86ec9c04eb6687b75831ebb84185786ac5}{original library} to introduce the notion of placeholders (before, the template was fixed forever), allowing for greater flexibility. The original rewrite (1.0) had really poor performance compared to the original library (only x3 improvement compared to no externalization, while the old library could be 20x faster), but we made some changes (v2.0) that correct this issue. Here is a benchmark we made on an article with 159 small pictures (ZX diagrams from the zx-calculus library):
+We completely rewrote the \href{https://github.com/leo-colisson/robust-externalize/commit/09a05a86ec9c04eb6687b75831ebb84185786ac5}{original library} to introduce the notion of placeholders (before, the template was fixed forever), allowing for greater flexibility. The original rewrite (1.0) had really poor performance compared to the original library (only x3 improvement compared to no externalization, while the old library could be 20x faster), but we made some changes (v2.0) that correct this issue to recover the original speed (at least when using compiled templates). Here is a benchmark we made on an article with 159 small pictures (ZX diagrams from the zx-calculus library):
\begin{itemize}
\item without externalization: 1mn25
\item with externalization, v2.0 (first run, not in parallel): 3mn05, so takes twice the time; but (first run in parallel) takes 60s (so faster by a factor of 1.5).
@@ -453,6 +506,45 @@ Cons of \url{https://github.com/sasozivanovic/memoize}:
Note that |remember picture| is not supported in both libraries, but we can provide multiple methods to disable externalizations when |remember picture| is used.
+\subsection{How to use with arXiv}\label{sec:arxiv}
+
+You can completely use this library with the arXiv's website (this documentation is also compiled in arXiv), but you need to follow a few steps due to arXiv's particularities:
+\begin{itemize}
+\item First, arXiv does NOT allow |-shell-escape|. So you either need to disable externalization (not recommended since this will of course increase the compilation time and will not work when working with non-latex code like python or external images), or you need to compile locally the document to cache all images locally\footnote{Make sure to recompile from scratch, by removing the .aux file, if your cached pictures can depend on counters (like the current page) that can change across compilations.}, and upload the |robustExternalize/| folder containing all cached images online in a zip file.
+\item Moreover, if you choose to upload the |robustExternalize/| folder, the arXiv website will automatically remove all |.pdf| files if a |.tex| file is present (which will break this library, since it puts all sources in the |.tex| file and the output in a |.pdf| file). The trick is to rename all the source |.tex| files into |.tex-backup| (this library will automatically recreate the |.tex| from the |.tex-backup| starting from v2.4). We provide two approaches for that:
+ \begin{itemize}
+ \item \textbf{Solution 1}: if you have python installed the most robust solution is to run
+\begin{verbatim}
+$ python robExt-prepare-for-arxiv.py
+\end{verbatim}
+ before sending the document to the arXiv. This will rename all the |.tex| files in the |robust-externalize| folder that have a matching |*.pdf| file into |.tex-backup|, and list these files in |robExt-arxiv-files-to-rename.txt|. Then, add in the preamble of your document:
+ \begin{codeexample}[code only]
+ \robExtConfigure{
+ rename backup files for arxiv,
+ }
+ \end{codeexample}
+ This will automatically rename back the |.tex-backup| files into |.tex| (without needing shell-escape), based on the |robExt-arxiv-files-to-rename.txt| file (if this file exists and if the files have not already been renamed: it is therefore safe to keep this option on even without running the python code), allowing the rest of the document to compile normally.
+ \item \textbf{Solution 2}: if you do \textbf{not} have python installed, you can simply run:
+ \begin{codeexample}[code only]
+ \robExtConfigure{
+ backup source for arxiv,
+ }
+ \end{codeexample}
+ This will automatically rename the source files |.tex| into |.tex-backup| (make sure to comment this line on the final pdf sent to the arXiv). Note however that this is less robust than solution 1 since the |.tex-backup| will be renamed into |.tex| only if it is in the source, but sometimes other |.tex| files might need to be renamed as well: for instance, |gnuplot| with |cairolatex| terminal creates two files |-gnuplot-.tex| and |-gnuplot-.pdf|, and this file will not be renamed with this method, so the |-gnuplot-.pdf| file will be lost.
+ \end{itemize}
+\item This should be enough to compile most documents. But note that since the arXiv uses a different Texlive version and might try to compile other document formats, it might be the case that the number of page varies from your original document: if you uses things like |forward counter=page|, it might cause you some troubles since your local cache might contain the cache for |page=42| while the arXiv would ask for the cached value for |page=45|, producing an error like |enable -shell-escape|. There are a few steps you can follow to fix these issues:
+ \begin{itemize}
+ \item First, make sure to have the same margins/paper on your local file and online (by default arXiv will create a document in |letterpaper|). To that end, you can force the paper format with |\documentclass[a4paper]{article}|.
+ \item ArXiv might try to compile with various output formats like eps, so it might help to force a pdf output by starting your document with |\pdfoutput=1| (not sure how helpful this is, it might already be forced when we insert a pdf?).
+ \item ArXiv will automatically remove all empty files. While for some files it is not an issue (aux files and compilation logs), if this file is the |.pdf| it will be an issue. So make sure to always generate non-empty output files.
+ \item If despite these options, arXiv still tries to fetch a cached value that is not present in your local cache, you can enable
+\begin{verbatim}
+\robExtConfigure{print source when saving}
+\end{verbatim}
+ This will print in the log file the content of the |.deps| file, of the |.tex| file, and the compilation command that would have been run without the error. You can then recreate these files in the cache and compile it locally. If you do not want to copy/paste the content of the file, it might be simpler to simply see the value that differs from your own local cache and just temporarily change this value in your local document to automatically generate the correct cache entry. If the value is obtained via |forward counter=page|, you can use |forward counter force value={page}{45}| to force the value of the counter.
+ \end{itemize}
+\end{itemize}
+
\section{Tutorial}
\subsection{Installation}
@@ -473,7 +565,7 @@ If you want to display a message in the pdf on how to manually compile the file
\noindent (otherwise, it will give you an error if |-shell-escape| is disabled and if some pictures are not yet cached)
-If you forget/do not want to enable |-shell-escape|, this will give you this kind of message:
+If you forget/do not want to enable |-shell-escape|, this will give you this kind of message with instructions to follow to compile without shell escape:
\noindent {
\robExtConfigure{
@@ -486,6 +578,32 @@ If you forget/do not want to enable |-shell-escape|, this will give you this kin
}
+If you use an editor, you can usually configure |-shell-escape| directly inside the editor, even on a per-document basis. Shell-escape is enabled by default on overleaf. In emacs/auctex, just add at the end of your document:
+\begin{verbatim}
+% Local Variables:
+% TeX-command-extra-options: "--shell-escape"
+% End:
+\end{verbatim}
+save, and run |M-x revert-buffer| (Note that it seems that |--shell-escape| can be used with one or two dashes on Linux, I am not sure about the number of dashes needed in Windows.)
+
+For TeXstudio, you can enable shell-escape on the current document by adding in your document:
+\begin{verbatim}
+% !TeX TXS-program:compile = txs:///pdflatex/[--shell-escape]
+\end{verbatim}
+and you might also want to enable:
+\begin{verbatim}
+\robExtConfigure{textstudio}
+\end{verbatim}
+to get clearer error messages as TeXstudio is \mylink{https://github.com/texstudio-org/texstudio/issues/1410}{fairly bad at parsing error messages} (see also |print whole file in error message|).
+
+If you use |latexmk| (with any editor), you can create a file called |.latexmkrc| containing:
+\begin{verbatim}
+$pdf_mode = 1;
+$pdflatex = 'pdflatex --shell-escape';
+\end{verbatim}
+
+For other editors, \mylink{https://tex.stackexchange.com/questions/598818/how-can-i-enable-shell-escape}{this answer} describe pretty accurately the solutions you have depending on your software.
+
\subsection{Caching a tikz picture}
If you only care about \tikzname's picture, you have 3 options:
@@ -610,11 +728,48 @@ Note that if you use the |tikzpictureC| or |tikzpicture| syntax, you want to add
\textbf{Important}: Note that the preset options can be specified in a number of places: in |\robExtConfigure| (possibly in a group, or inside a preset), in the options of the picture, in the default options of |cacheEnvironment| and |cacheCommand| etc. Most options can be used in all these places, the only difference being the scope of the options.
+If you find yourself duplicating code between the main document and the preamble of the cached file, we provide multiple solutions with different properties:
+\begin{itemize}
+\item Recommended: |\newcommandAutoForward| etc, to automatically forward specific macros/colors etc: see \cref{sec:forwardIntro}. Very useful if you want maximum purity without annoying recompilation.
+\item |\runHereAndInPreambleOfCachedFiles|: mostly useful if you want to always add a text both in the current file and in the cached files, like a font etc.
+\item Share a common input file with or without dependencies (see \cref{sec:dependencies}), useful if you need to work with external files or if you do NOT want purity (i.e.\ you can choose not to recompile the file even if its content changes).
+\end{itemize}
+
+|\runHereAndInPreambleOfCachedFiles{XXX}| is very simple (need at least version 2.3), as it is simply a shortcut for typing |XXX| in the current file and in the preamble of the cached files (default to latex preset). For instance if you want the current file and all cached files to use the Times New Roman font, you can do:
+
+\begin{codeexample}[code only]
+% By default adds
+\runHereAndInPreambleOfCachedFiles{
+ \usepackage{fontspec}
+ % need lualatex or xelatex to compile
+ \setmainfont{Times New Roman}
+}
+
+\robExtConfigure{
+ add to preset={latex}{
+ use lualatex, % Make sure to compile with lualatex the cached images.
+ },
+}
+\end{codeexample}
+
+You can also define your common macros (even if we recommend |\newcommandAutoForward| to avoid frequent recompilations when the definitions changes):
+\begin{codeexample}[width=0pt,vbox]
+\runHereAndInPreambleOfCachedFiles{
+ \def\name#1{The great lady #1 and her friends.}
+}
+
+\cacheTikz
+This is the picture of \name{Alice}:
+\begin{tikzpicture}
+ \node[fill=orange]{\name{Alice}};
+\end{tikzpicture}
+\end{codeexample}
+
\subsection{Dependencies}\label{sec:dependencies}
-\textbf{Note: dependencies can sometimes be advantageously replaced with auto-forwarding of arguments, cf.\ \cref{sec:forwardIntro}.}
+\textbf{Note: dependencies can sometimes be advantageously replaced with auto-forwarding of arguments, cf.\ \cref{sec:forwardIntro}, or |\runHereAndInPreambleOfCachedFiles|.}
-It might be handy to have a file that is loaded in both the main document and in the cached pictures. For instance, if you have a file |common_inputs.tex| that you want to input in both the main file and in the cached files, that contains, say:\\
+It might be handy to have a file that is loaded in both the main document and in the cached pictures. For instance, if you have a logo that might be included in the cached files, or if you have a file |common_inputs.tex| that you want to input in both the main file and in the cached files, that contains, say:\\
|\def\myValueDefinedInCommonInputs{42}|\\
then you can add it as a dependency this way (here we use the |latex| preset that does not wrap the code inside a |tikzpicture| only to illustrate that we can also cache things that are not generated by tikz):
\begin{codeexample}[width=0pt,vbox]
@@ -628,6 +783,13 @@ Note that the placeholder |__ROBEXT_WAY_BACK__| contains the path from the cache
You can note that we used |add dependencies={common_inputs.tex}|: this allows us to recompile the files if |common_inputs.tex| changes. If you do not want this behavior (e.g. |common_inputs.tex| changes too often and you do not want to recompile everything at every change), you can remove this line, but beware: if you do a breaking changes in |common_inputs.tex| (e.g.\ redefine |42| to |43|), then the previously cached picture will not be recompiled! (So you will still read 42 instead of 43.)
+Sometimes, it can also be useful to copy a file in the cache folder. This can be done via:
+\begin{codeexample}[code only]
+\robExtConfigure{
+ copy file to cache={zx-calculus.sty},
+}
+\end{codeexample}
+
\subsection{Wrap arbitrary environments}
You can wrap arbitrary environments using the already presented |cacheEnvironment| and |cacheCommand|, where the first mandatory argument is the name of the environment/macro, and the second mandatory argument contains the default preset. |cacheEnvironment| works for any environment while |cacheCommand| might need a bit of help to determine the signature of the macro if the function is defined via xparse. Long story short, |O{foo}| is an optional argument with default value foo, |m| is a mandatory argument. By default, you can pass an optional arguments via the first argument enclosed in |<>|:
@@ -725,6 +887,7 @@ Some text %
You can feed data from the main document to the cached file using placeholders, since |set placeholder eval={__foo__}{\bar}| will evaluate |\bar| and put the result in |__foo__|. For instance, if the picture depends on the current page, you can do:
+\message{We will export the page: \thepage}
\begin{codeexample}[width=0pt,vbox]
\begin{tikzpictureC}<set placeholder eval={__thepage__}{\thepage}>
\node[rounded corners, fill=red]{The current page is __thepage__.};
@@ -820,6 +983,105 @@ We compute this data that is long to compute:
We computed the cached value \myLongResult.
\end{codeexample}
+\subsection{A note on font handling}
+
+Cached pictures are basically simple latex files that are compiled in a separate |standalone| document. Therefore, if the main document loads a different font, there is no reason for the cached document to also use that font. Fully-automatically forwarding the current font by default is not so easy because there are so many ways to load a font in LaTeX (by loading a package like |\usepackage{times}|, by using xelatex or lualatex, by calling locally |\rmfamily|, by loading a different class… and here I'm not even mentioning math font where each symbol \mylink{https://tex.stackexchange.com/questions/603475/is-there-any-command-to-find-out-the-current-math-font-used)}{can use a different font}, and this is even more complicated if the main file is compiled with a different engine (e.g.\ what should I do if the main document is compiled with lualatex but the inner cached images are compiled with pdflatex, that supports very few fonts by default?). For these reasons, it is simpler to simply let the user load fonts as they want, for instance using something like:
+\begin{codeexample}[width=0pt]
+\robExtConfigure{
+ add to preset={latex}{
+ add to preamble={\usepackage{times}},
+ },
+}
+
+\begin{tikzpictureC}
+\node[fill=green]{See I am using times font};
+\end{tikzpictureC}
+\end{codeexample}
+or:
+\begin{codeexample}[width=0pt]
+\robExtConfigure{
+ add to preset={latex}{
+ add to latex options={12pt},
+ },
+}
+
+\begin{tikzpictureC}
+\node[fill=green]{See I am using a 12pt font};
+\end{tikzpictureC}
+\end{codeexample}
+
+But if you want to use the same font as the current document, you might want to avoid code duplication (this might also be useful for any arbitrary code). Since v2.3, you can do:
+\begin{codeexample}[code only]
+\runHereAndInPreambleOfCachedFiles{
+ \usepackage{fontspec}
+ % need lualatex or xelatex to compile
+ \setmainfont{Times New Roman}
+}
+
+\robExtConfigure{
+ add to preset={latex}{
+ use lualatex, % Make sure to compile with lualatex the cached images.
+ },
+}
+\end{codeexample}
+and it will automatically compile the cached images with lualatex, and configure the font of the current document and of the cached documents to follow |Times New Roman|.
+
+If you like to often change the font in the document, you can also do something like that to always compile the document with the font currently in use if you use lualatex (this code fails with \mylink{https://tex.stackexchange.com/questions/705208/get-current-font}{xelatex}, currently trying to understand why):
+\begin{codeexample}[code only]
+\usepackage{fontspec}
+\setmainfont{Times New Roman}
+
+%% needed since \f@family contains a @ in its name:
+\makeatletter
+\def\myCurrentFont{\f@family}
+\makeatother
+
+\robExtConfigure{
+ add to preset={latex}{
+ use lualatex,
+ % create a new placeholder containing the name of the current font:
+ set placeholder eval={__MY_FONT__}{\myCurrentFont},
+ add to preamble={
+ \usepackage{fontspec}
+ \setmainfont{__MY_FONT__}
+ },
+ },
+}
+\end{codeexample}
+If you want this to work on xelatex, you can either manually attribute a |NFSSFamily| name like:
+\begin{codeexample}[code only]
+\runHereAndInPreambleOfCachedFiles{
+ \usepackage{fontspec}
+ % need lualatex or xelatex to compile, make sure to use a different NFSSFamily for each new font you add here
+ \setmainfont[NFSSFamily=tmsnr]{Times New Roman}
+}
+\end{codeexample}
+and use the above solution for lualatex (you can change the font with |\fontfamily{tmsnr}\selectfont|), or do instead something like this:
+\begin{codeexample}[code only]
+% Create a new command \mysetmainfont which forwards the font to the picture.
+\NewDocumentCommand{\mysetmainfont}{m}{%
+ \def\myCurrentFont{#1}% Stores the name of the current font in \myCurrentFont
+ \setmainfont{#1}%
+}
+
+% Use mysetmainfont from now to change font:
+\mysetmainfont{Times New Roman}
+
+\usepackage{robust-externalize}
+\robExtConfigure{
+ add to preset={latex}{
+ use xelatex,
+ set placeholder eval={__MY_FONT__}{\myCurrentFont},
+ add to preamble={
+ \usepackage{fontspec}
+ \setmainfont{__MY_FONT__}
+ },
+ },
+}
+\end{codeexample}
+
+
+
\subsection{Compile in parallel}
Make sure to have xargs installed (installed by default on most linux, on Windows you need to install the lightweight GNU On Windows (Gow) \url{https://github.com/bmatzelle/gow}), and type in your preamble:
\begin{codeexample}[code only]
@@ -1162,7 +1424,8 @@ We also provide support for other languages, notably |bash|, but it is relativel
set -e
__ROBEXT_MAIN_CONTENT__
# Create the pdf file to certify that no compilation error occured
-touch "__ROBEXT_OUTPUT_PDF__"
+# (non empty file to avoid arXiv error)
+echo "ok" > "__ROBEXT_OUTPUT_PDF__"
\end{PlaceholderFromCode}
\robExtConfigure{
@@ -1216,7 +1479,9 @@ plt.savefig("__ROBEXT_OUTPUT_PDF__")
If you want to recompile a file (e.g. an untracked dependency was changed\dots{} and you do not want to track it to avoid recompilation when you change a single line in this file), you can use the |recompile| style since v2.1:
-\begin{codeexample}[vbox]
+\begin{codeexample}[vbox,
+ %TURN_INTO_CODE_ONLY_ARXIV
+ ]
\cacheEnvironment{tikzcd}{tikz, add to preamble={\usepackage{tikz-cd}}}
\begin{tikzcd}<recompile>
A \rar & B
@@ -1248,7 +1513,7 @@ Note also that we usually define two names for each function, one normal and one
\subsection{Placeholders}\label{sec:placeholders}
-Placeholders are the main concept allowing this library to generate the content of a source file based on a template (a template will itself be a placeholder containing other placeholders). A placeholder is a special strings like |__COLOR_IMAGE__| that should start and end with two underscores, ideally containing no space or double underscores inside the name directly. Placeholders are inserted for instance in a string and will be given a value later. This value will be used to replace (recursively) the placeholder in the template. For instance, if a placeholder |__LIKES__| contains |I like __FRUIT__ and __VEGETABLE__|, if the placeholder |__FRUIT__| contains |oranges| and if the placeholder |__VEGETABLE__| contains |salad|, then evaluating |__LIKES__| will output |I like oranges and salad.|
+Placeholders are the main concept allowing this library to generate the content of a source file based on a template (a template will itself be a placeholder containing other placeholders). A placeholder is a special strings like |__COLOR_IMAGE__| that should start and end with two underscores, ideally containing no space or double underscores inside the name directly (we might use this property even more in a future release to improve further the efficiency). Placeholders are inserted for instance in a string and will be given a value later. This value will be used to replace (recursively) the placeholder in the template. For instance, if a placeholder |__LIKES__| contains |I like __FRUIT__ and __VEGETABLE__|, if the placeholder |__FRUIT__| contains |oranges| and if the placeholder |__VEGETABLE__| contains |salad|, then evaluating |__LIKES__| will output |I like oranges and salad.|
Note that you are not strictly forced to follow the above convention (it allows us to optimize the code to find and replace placeholders), but in that case you should enable |not all placeholders have underscores|.
@@ -1405,6 +1670,18 @@ Compare with:
\placeholderFromContent{__NAME__}{Alice}
The (unexpanded) template contains \texttt{\getPlaceholderNoReplacement{__LIKES__}}
\end{codeexample}
+Note that this macro is expandable, which can be helpful for instance if you use |siunitx| that expects an expandable content:
+\begin{codeexample}[width=0pt,vbox]
+\setPlaceholder{__TEST__}{4.42345}
+\num[round-mode=figures,round-precision=3]{\getPlaceholderNoReplacement{__TEST__}}
+\end{codeexample}
+This is contrary to |\getPlaceholder| that is not expandable, so if you do want expandable |\getPlaceholder| with replacements, you should rather first evaluate the placeholder with |\getPlaceholderInResult{__TEST_VARIABLE__}|:
+\begin{codeexample}[width=0pt,vbox]
+\setPlaceholder{__TEST_A__}{4.42345}
+\setPlaceholder{__TEST__}{__TEST_A__}
+\getPlaceholderInResult{__TEST_A__}
+\num[round-mode=figures,round-precision=3]{\robExtResult}
+\end{codeexample}
\end{pgfmanualentry}
\subsubsection{Setting a value to a placeholder}
@@ -2297,9 +2574,16 @@ plt.ylabel('Number of futurestud.io Tutorials')
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/set compilation command=\marg{compilation command}\@nil
+ \extractkey/robExt/set compilation command create if no error=\marg{compilation command}\@nil
+ \extractkey/robExt/set compilation command move if no error=\marg{compilation command}\@nil
\makeatother%
\pgfmanualbody
- Style that alias to |set placeholder={__ROBEXT_COMPILATION_COMMAND__}{#1}|, in order to define the placeholder that will hold the compilation command.
+ |set compilation command| is equivalent to |set placeholder={__ROBEXT_COMPILATION_COMMAND__}{#1}|, in order to define the placeholder that will hold the compilation command.
+
+ Then, |set compilation command move if no error| (new in v2.4)
+ is like |set compilation command| except that it will copy the file located in |__ROBEXT_OUTPUT_PDF__-tmp| into |__ROBEXT_OUTPUT_PDF__| if the command succeeds (returns a status code of 0), and otherwise it will not create the |__ROBEXT_OUTPUT_PDF__| at all, creating an error message. This is needed by some programs that will create an output file even if an error occurs, for instance wget will still create an empty file if there is no internet connection, producing no error during the compilation, which can be confusing.
+
+ |set compilation command create if no error| (new in v2.4) will, on the other hand, create an empty |__ROBEXT_OUTPUT_PDF__| file if the command succeeds (only useful if you use a custom include command).
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -2353,7 +2637,9 @@ plt.ylabel('Number of futurestud.io Tutorials')
\pgfmanualbody
(new to v2.1) |recompile| will force a compilation even if the image is already cached (mostly useful if you made a change to a non-tracked dependency). Note that since this library does not want to remove any file on the hard drive (we do not want to risk to remove important files in case of a bug), this command will NOT clear the auxiliary files already present, so for maximum purity, ensure that your compiling command is idempotent (so that compiling twice gives the same outcome as compiling once).
-\begin{codeexample}[vbox]
+\begin{codeexample}[vbox,
+ %TURN_INTO_CODE_ONLY_ARXIV
+ ]
\cacheEnvironment{tikzcd}{tikz, add to preamble={\usepackage{tikz-cd}}}
\begin{tikzcd}<recompile>
A \rar & B
@@ -2393,6 +2679,15 @@ You want to delete the file \texttt{\filetodeleteInCache.pdf}. %
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \extractcommand\robExtMv\@@
+ \extractcommand\robExtCp\@@
+ \pgfmanualbody
+ (new in v2.4) Respectively expands to |mv| and |cp| in linux/unix and to |move| and |copy| in Windows (needed to create a compilation command that works in both linux and windows). Note that |set compilation command| does NOT expand its argument by default and spaces after macros are removed by latex, so you need to use |/.expanded| and |\space| like in:
+ \begin{codeexample}[code only]
+ set compilation command/.expanded={\robExtCp\space"__ROBEXT_SOURCE_FILE__" "__ROBEXT_OUTPUT_PDF__"}
+ \end{codeexample}
+\end{pgfmanualentry}
\subsubsection{Options to configure the inclusion command}
@@ -2413,19 +2708,26 @@ The inclusion command is the command that is run to include the cached file back
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/custom include command=\marg{include command}\@nil
+ \extractkey/robExt/include command is input=\opt{\oarg{additional code to run}}\@nil
\makeatother%
\pgfmanualbody
- Sets the command to run to include the compiled file, after checking if the file has been correctly compiled and loading |*-out.tex| (useful to pass information back to the pdf).
+ Sets the command to run to include the compiled file, after checking if the file has been correctly compiled and loading |*-out.tex| (useful to pass information back to the pdf). |include command is input={SOME CODE}| is a shortcut for:
+\begin{verbatim}
+custom include command={SOME CODE\input{\robExtAddCachePathAndName{\robExtFinalHash.pdf}}},
+\end{verbatim}
\end{pgfmanualentry}
\begin{pgfmanualentry}
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/do not include pdf\@nil
+ \extractkey/robExt/include command is input=\opt{additional command}\@nil
\makeatother%
\pgfmanualbody
- Do not include the pdf. Useful if you only want to compile the file but use it later (note that you should still generate a |.pdf| file, possibly empty, to indicate that the compilation runs smootly). Equivalent to:\\
+ |do not include pdf| do not include the pdf. Useful if you only want to compile the file but use it later (note that you should still generate a |.pdf| file, possibly empty, to indicate that the compilation runs smootly). Equivalent to:\\
|custom include command={}|
+ Use |include command is input| (v2.3 and after) in order to specify that you should |\input| the |.pdf| file (note that despite the extension, it should still contain a LaTeX code). You can also specify an optional command to run before. Equivalent to:
+ |custom include command={#1\input{\robExtAddCachePathAndName{\robExtFinalHash.pdf}}}|
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -2465,6 +2767,16 @@ The inclusion command is the command that is run to include the cached file back
By default, the include commands runs |\includegraphics| on the pdf, and possibly raises it if needed. You can customize the arguments passed to |\includegraphics| here.
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/add cache to graphicspath\@nil
+ \makeatother%
+ \pgfmanualbody
+ This will add the folder containing the cache in the |\graphicspath{}|. Mostly useful if you need to input a file from the cache that does |\includegraphics{foo}| where |foo| is an image from the cache itself (looking at you gnuplot).
+\end{pgfmanualentry}
+
+
\subsubsection{Configuration of the cache}
If needed, you can configure the cache:
@@ -2497,6 +2809,24 @@ If needed, you can configure the cache:
\begin{pgfmanualentry}
\makeatletter%
\def\extrakeytext{style, }
+ \extractkey/robExt/set output directory=\marg{output directory}\@nil
+ \makeatother%
+ \pgfmanualbody
+ If you compile with |--output-directory build|, you also need to tell this library that you are compiling with |--output-directory build|. As I can't find a reliable way to get this value, even using |TEXMF_OUTPUT_DIRECTORY|, you need to specify manually the compilation directory. To do that, you can either compile with:
+ \begin{codeexample}[code only]
+ pdflatex -shell-escape -output-directory=build "\def\robExtOutputDirectory{build}\input{test.tex}"
+ \end{codeexample}
+ or add in your file:
+ \begin{codeexample}[code only]
+ \robExtConfigure{
+ set output directory=build,
+ }
+ \end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
\extractkey/robExt/no cache folder\@nil
\makeatother%
\pgfmanualbody
@@ -2580,6 +2910,7 @@ Some text %
\def\extrakeytext{style, }
\extractkey/robExt/command if no externalization\@nil
\extractkey/robExt/command if externalization\@nil
+ \extractkey/robExt/run command if externalization=\marg{code}\@nil
\makeatother%
\pgfmanualbody
You can easily change the command to run if externalization is disabled using by setting the \textbf{.code} of this key. By default, it is configured as:\\
@@ -2589,7 +2920,7 @@ command if no externalization/.code={%
}
\end{verbatim}
Unless you know what you are doing, you should include |\robExtDisableTikzpictureOverwrite| as it is often necessary to avoid infinite recursion when externalization is disabled and the original command has been replaced with a cached version (for instance done by |\cacheTikz|). Note that if you write your own style, try to modify |__ROBEXT_MAIN_CONTENT__| so that it can be included as-it in a document: this way you do not need to change this command.
- You can also use |command if externalization/.append code={...}| if you want to run a code only if externalization is enabled (this is used for instance by the |forward| functionality).
+ You can also use |command if externalization/.append code={...}| if you want to run a code only if externalization is enabled (this is used for instance by the |forward| functionality), but we advise you rather to use |run command if externalization={...}| as this will also work if the style is executed while |command if externalization| is already running (this might occur when calling the style inside |if matches word|, for instance when forwarding colors).
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -2665,6 +2996,23 @@ In order to enforce reproducibility, you should tell what are the files that you
Note that the placeholder |__ROBEXT_WAY_BACK__| contains the path from the cache folder (containing the |.tex| that will be cached) to the root folder.\\ This way, you can easily input files contained in the root folder.
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \extractcommand\copyFileToCache\@@
+ \extractcommand\forceCopyFileToCache\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/copy file to cache=\marg{file}\@nil
+ \makeatother%
+ \pgfmanualbody
+ It can sometimes be handy to copy a file to the cache folder to avoid using |__ROBEXT_WAY_BACK__| for instance to refer to another file. This can be done with |copy file to cache|, either in a preset or in |\robExtConfigure| like:
+\begin{codeexample}[code only]
+\robExtConfigure{
+ copy file to cache={zx-calculus.sty},
+}
+\end{codeexample}
+Note that |copy file to cache| will always compare the md5 sum to check if a copy must be done or not.
+\end{pgfmanualentry}
+
\subsubsection{Forward macros}\label{sec:forward}
(since v2.1)
@@ -2762,6 +3110,7 @@ Really involved macros (e.g.\ defined inside libraries) might call many other ma
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/forward counter=counter to forward\@nil
+ \extractkey/robExt/forward counter force value=\marg{counter to forward}\marg{value of counter}\@nil
\makeatother%
\pgfmanualbody
Forward a counter:
@@ -2770,6 +3119,12 @@ Really involved macros (e.g.\ defined inside libraries) might call many other ma
\node[rounded corners, fill=red]{The current page is \thepage.};
\end{tikzpictureC}
\end{codeexample}
+The force value also assigns a value to the counter irrespective of the current value (might be useful for instance to generate a cached value for the arXiv).
+\begin{codeexample}[width=0pt]
+\begin{tikzpictureC}<forward counter force value={page}{65}>
+ \node[rounded corners, fill=red]{The current page is \thepage.};
+\end{tikzpictureC}
+\end{codeexample}
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -2794,13 +3149,25 @@ but also with colors defined with |\colorlet|:
\node[fill=myviolet,yshift=-1cm]{B};
\end{tikzpictureC}
\end{codeexample}
-Note that using |if matches word|, you can also automatically forward colors:
+Note that using |if matches word|, you can also automatically forward colors. This command also scales better than |if matches|: if |if matches| is used to register $N$ words, the compilation time will increase for each new |if matches| (since we need to check each time if the string contains the expression). |if matches word|, on the other hand, is more clever, and extracts in a single loop all the words of the string: the running time is therefore independent of the number of times |if matches word| was called. You can call |if matches word| outside of any preset like in:
\begin{codeexample}[width=0pt]
\definecolor{myred}{HTML}{F01122}
\colorlet{myviolet}{blue!50!myred}
\colorlet{mypink}{pink!90!orange}
\robExtConfigure{
- add to preset={tikz}{
+ if matches word={mypink}{forward color=mypink},
+}
+\begin{tikzpictureC}
+ \node[fill=mypink,yshift=-1cm]{B};
+\end{tikzpictureC}
+\end{codeexample}
+And this will automatically allow all presets based on |latex| to forward this color (see also |\definecolorAutoForward| to do that even quicker). You can also simply call it on any preset of your choice like:
+\begin{codeexample}[width=0pt]
+\definecolor{myred}{HTML}{F01122}
+\colorlet{myviolet}{blue!50!myred}
+\colorlet{mypink}{pink!90!orange}
+\robExtConfigure{
+ add to preset={latex}{
if matches word={mypink}{forward color=mypink},
},
}
@@ -2808,7 +3175,7 @@ Note that using |if matches word|, you can also automatically forward colors:
\node[fill=mypink,yshift=-1cm]{B};
\end{tikzpictureC}
\end{codeexample}
-but since this is a bit long to type, we provide a shortcut:
+or, equivalently:
\begin{codeexample}[width=0pt]
\definecolor{myred}{HTML}{F01122}
\colorlet{myviolet}{blue!50!myred}
@@ -2826,9 +3193,11 @@ but since this is a bit long to type, we provide a shortcut:
\makeatletter%
\def\extrakeytext{style, }
\extractkey/robExt/auto forward\@nil
+ \extractkey/robExt/auto forward only macros\@nil
+ \extractkey/robExt/auto forward words\@nil
\makeatother%
\pgfmanualbody
- Enable automatic forwarding of macros marked with |*AutoForward| commands or |\configIfMacroPresent|. This command naively extracts all used macro via a simple regex match and forwards them/execute the style configured in |\configIfMacroPresent| if it exists.
+ |auto forward| enables automatic forwarding of macros marked with |*AutoForward| commands or |\configIfMacroPresent| or |if matches word|. This command naively extracts all used macros via a simple regex match and forwards them/execute the style configured in |\configIfMacroPresent| if it exists. It does a similar thing for words registered via |if matches word| or |register word with namespace|. If you want to only forward macros or words, you can use |auto forward only macros| or |auto forward words|.
\begin{codeexample}[vbox]
\cacheTikz
\robExtConfigure{add to preset={tikz}{auto forward}}
@@ -2878,8 +3247,8 @@ but since this is a bit long to type, we provide a shortcut:
\extractcommand\ProvideExpandableDocumentCommandAutoForward\marg{macro}\marg{arg spec}\opt{\oarg{additional style}}\marg{definition}\@@
\extractcommand\DeclareExpandableDocumentCommandAutoForward\marg{macro}\marg{arg spec}\opt{\oarg{additional style}}\marg{definition}\@@
\extractcommand\defAutoForward\marg{macro}\opt{\oarg{def-style arg spec}}\marg{macro}\opt{\oarg{additional style}}\@@
- \extractcommand\genericAutoForward\opt{*}\opt{\oarg{preset}}\marg{string to match}\opt{\oarg{additional style}}\marg{code to execute}\@@
- \extractcommand\genericAutoForwardStringMatch\opt{*}\opt{\oarg{preset}}\marg{string to match}\opt{\oarg{additional style in preset}}\opt{\oarg{additional style outside preset}}\marg{code to execute}\@@
+ \extractcommand\genericAutoForward\opt{*}\opt{\oarg{preset}}\opt{\oarg{namespace}}\marg{word}\opt{\oarg{additional style}}\marg{code to run}\@@
+ \extractcommand\genericAutoForwardStringMatch\opt{*}\opt{\oarg{preset}}\marg{string}\opt{\oarg{additional style}}\marg{code to run}\@@
\pgfmanualbody
\begin{verbatim}
\newcommandAutoForward{\macro}[nb args][default value]{def}[STYLE]
@@ -2908,7 +3277,7 @@ but since this is a bit long to type, we provide a shortcut:
\end{tikzpicture}
\end{codeexample}
- This works similarly for other commands (note that for |\defAutoForward|, you need to put the arguments in a bracket, like |\defAutoForward\myMacro[#1 and #2]{Hey #1, #2}| for |\def\myMacro#1 and #2{Hey #1, #2}|). |\genericAutoForward| and |\genericAutoForwardStringMatch| are a bit special (for now these two commands are alias, but only use the first one if the string is surrounded by non-letter characters as we plan to make that special case more efficient later as it uses internally |if matches word|), as it can be used to run any code assuming that |string to match| is present. For instance, you can use it to automatically forward the code that defines a new tikz style assuming |mystyle| is preset:
+ This works similarly for other commands (note that for |\defAutoForward|, you need to put the arguments in a bracket, like |\defAutoForward\myMacro[#1 and #2]{Hey #1, #2}| for |\def\myMacro#1 and #2{Hey #1, #2}|). |\genericAutoForward| and |\genericAutoForwardStringMatch| are a bit special, as it can be used to run any code assuming that |word|/|string to match| is present (|\genericAutoForward| is more efficient as it does not scale with the number of words, but do not allow spaces etc in the name). For instance, you can use it to automatically forward the code that defines a new tikz style assuming |mystyle| is preset:
\begin{codeexample}[width=0pt]
\cacheTikz
\genericAutoForward{mystyle}{
@@ -2943,6 +3312,68 @@ This will also run the code to define it in the current document (practical for
};
\end{tikzpicture}
\end{codeexample}
+ \begin{codeexample}[vbox]
+ % space is not allowed in the name with this more efficient version:
+ \robExtGenericAutoForward{mystyle}{%
+ \tikzset{%
+ mystyle/.style={fill=#1!30!white,text=#1!40!black},
+ }%
+ }
+ \begin{tikzpictureC}
+ \node[mystyle=green]{My style automatically forwarded};
+ \end{tikzpictureC}
+ \end{codeexample}
+ \begin{codeexample}[vbox]
+ % space is allowed in the name with this slightly less efficient version:
+ \robExtGenericAutoForwardStringMatch{my style}{%
+ \tikzset{%
+ my style/.style={fill=#1!30!white,text=#1!40!black},
+ }%
+ }
+ \begin{tikzpictureC}
+ \node[my style=green]{My style with a space in the name automatically forwarded};
+ \end{tikzpictureC}
+ \end{codeexample}
+ Note that by default, this forwards elements in the |latex| preset, but you can change it via |preset|. You can also configure additional style to run, and choose another namespace for the word version (practical only if you want to forward different codes to different presets: note that a single namespace is allowed per preset).
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\runHereAndInPreambleOfCachedFiles\opt{\oarg{preset}}\marg{code}\@@
+ \pgfmanualbody
+ (from v2.3) This will run |code| right now and it will add it in the preamble of the files that use the preset |preset| (defaults to |latex|). This is practical to avoid duplicating the code into |add to preamble|. For instance, if want the configure the font of the current document and of all latex documents at the same time, use:
+\begin{codeexample}[code only]
+\runHereAndInPreambleOfCachedFiles{
+ \usepackage{fontspec}
+ \setmainfont{Times New Roman}
+}
+
+\robExtConfigure{
+ add to preset={latex}{
+ use lualatex, % Make sure to compile with lualatex the cached images.
+ },
+}
+\end{codeexample}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\definecolorAutoForward\marg{color}\marg{model}\marg{value}\opt{\oarg{additional style}}\@@
+ \extractcommand\colorletAutoForward\marg{color}\marg{value}\opt{\oarg{additional style}}\@@
+ \pgfmanualbody
+ Define colors like |\definecolor| and |\colorlet|, but also runs
+\begin{verbatim}
+if matches word={COLOR}{forward color=COLOR}
+\end{verbatim}
+ to automatically forward the color (this will forward it only in latex-based presets). You can provide additional style to run as well in option.
+ \begin{codeexample}[vbox]
+ \definecolorAutoForward{myred}{HTML}{F01122}
+ \colorletAutoForward{myviolet}{blue!50!myred}
+ \begin{tikzpictureC}
+ \node[fill=myred,yshift=-1cm]{Uses myred};
+ \end{tikzpictureC}
+ \begin{tikzpictureC}
+ \node[fill=myviolet,yshift=-1cm]{Myviolet};
+ \end{tikzpictureC}
+ \end{codeexample}
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -2974,9 +3405,12 @@ This will also run the code to define it in the current document (practical for
\extractkey/robExt/if matches=\marg{string}\marg{style to apply}\@nil
\extractkey/robExt/if matches word=\marg{string}\marg{style to apply}\@nil
\extractkey/robExt/if matches regex=\marg{latex3 regex}\marg{style to apply}\@nil
+ \extractkey/robExt/register word with namespace=\marg{namespace}\marg{word}\marg{style}\@nil
+ \extractkey/robExt/auto forward words\@nil
+ \extractkey/robExt/auto forward words namespace=\marg{namespace}\@nil
\makeatother%
\pgfmanualbody
- Apply the corresponding style if the string (resp.\ regex in \LaTeX{}3 format) matches is matched in the content. As of today, |if matches word| and |if matches| are equivalent, but I plan to make |if watches word| more efficient\footnote{Scaling with $O(s)$ instead of $O(sn)$, where $s$ is the size of the string typed in |cacheMe| and $n$ is the number of times |if matches| is used, for instance when replacing multiple strings.}, and make it only match words that are made of consecutive letters |[A-Za-z]|. The regex version can be more expressive, but is significantly slower (it can easily multiply by 2 the compilation time).
+ |if matches *| applies the corresponding style if the string (resp.\ word or regex in \LaTeX{}3 format) matches is matched in the content. |if matches word| is more efficient that |if matches string| since the running time is independent of the number of times |if matches word| is called\footnote{Scaling with $O(s)$ instead of $O(sn)$, where $s$ is the size of the string typed in |cacheMe| and $n$ is the number of times |if matches| is used, for instance when replacing multiple strings.}. |if matches word| make it only match words that are mostly made of consecutive letters and numbers |[A-Za-z0-9]| (more precisely separated by elements in |\robExtWordSeparators|). The regex version can be more expressive, but is significantly slower (it can easily multiply by 2 the compilation time).
\begin{codeexample}[vbox]
\robExtConfigure{
add to preset={my python}{
@@ -3021,8 +3455,10 @@ Some text %
\draw[->] (0,0) to[bend left] (my original node);
\end{tikzpicture}
\end{codeexample}
+Note that to make |if matches word| even more efficient, you can call it before the preset. It will "register" the corresponding word with |register word| (itself a shortcut for |register word with namespace| with an empty namespace), and call |auto forward words| (shortcut for |auto forward words namespace={}|) in the |latex| preset (or in the current preset if we are already in a preset) to forward all words registered in the corresponding namespace (empty by default). Unless you want to forward different words to different presets, these more advanced functions involving namespaces should not be really useful for the end user.
\end{pgfmanualentry}
+
\subsubsection{Pass compiled file to another template}\label{sec:passOutputToOtherTemplate}
It can sometimes be handy to use the result of a previous cached file to cache another file, or to do anything else (e.g.\ it can also be practical to debug an issue). |name output| can be used to do that
@@ -3490,7 +3926,7 @@ outputTxt="__ROBEXT_OUTPUT_PREFIX__-out.txt"
outputTex="__ROBEXT_OUTPUT_PREFIX__-out.tex"
outputPdf="__ROBEXT_OUTPUT_PDF__"
\end{verbatim}
-in order to quit when an error occurs, and to define two variables containing the path to the |pdf| file and to the file that is read by the |verbatim output| setting (that just apply a |\verbatiminput| on that file). Finally, it also creates the file |outputPdf| with |touch| in order to notify that the compilation succeeded.
+in order to quit when an error occurs, and to define two variables containing the path to the |pdf| file and to the file that is read by the |verbatim output| setting (that just apply a |\verbatiminput| on that file). Finally, it also creates the file |outputPdf| with |echo "ok"| in order to notify that the compilation succeeded.
In practice:
\begin{codeAndResult}
@@ -3530,6 +3966,230 @@ This file contains:
You might also like to use |name output=yourfile| that will create two macros |\yourfile| and |\yourfileInCache|, equal respectively to the prefix |robExt-somehash| and |pathOfCache/robExt-somehash|.
+\subsubsection{Online images}
+
+We also provide support for online images since v2.3.
+\begin{pgfmanualentry}
+ \extractcommand\includegraphicsWeb\opt{<robExt options>}\opt{\oarg{includegraphics options}}\marg{url image}\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/web image\@nil
+ \extractkey/robExt/web image/wget\@nil
+ \extractkey/robExt/web image/curl\@nil
+ \makeatother%
+ \pgfmanualbody
+ |\includegraphicsWeb| is used in place of |\includegraphics| to download online images:
+\begin{codeexample}[width=0pt,vbox]
+Here is a cat downloaded online: \includegraphicsWeb[width=3cm]{http://placekitten.com/400/300}.
+\end{codeexample}
+By default, the engine uses |wget| in linux (since it is installed by default) and |curl| on windows (should also be installed by default on recent windows). But you can change it by modifying the |web image| preset (or using the optional robExt options that are loaded after |web image|):
+\begin{codeexample}[width=0pt,vbox]
+\robExtConfigure{
+ add to preset={web image}{
+ curl
+ },
+}
+
+Here is a cat downloaded online: \includegraphicsWeb[width=3cm]{http://placekitten.com/400/303}.
+\end{codeexample}
+By default, the |wget| and |curl| presets are defined as:
+\begin{verbatim}
+wget/.style={
+ set compilation command={wget "__ROBEXT_MAIN_CONTENT__" -O "__ROBEXT_OUTPUT_PDF__"},
+},
+curl/.style={
+ set compilation command={curl "__ROBEXT_MAIN_CONTENT__" -L -o "__ROBEXT_OUTPUT_PDF__"},
+},
+\end{verbatim}
+\end{pgfmanualentry}
+
+\subsubsection{Gnuplot}
+
+We also provide support for gnuplot since v2.3.
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/gnuplot\@nil
+ \extractkey/robExt/gnuplot/set terminal=\marg{terminal and options}\@nil
+ \extractkey/robExt/gnuplot/pdf terminal=\opt{pdf terminal options}\@nil
+ \extractkey/robExt/gnuplot/tikz terminal=\opt{tikz terminal options}\@nil
+ \makeatother%
+ \pgfmanualbody
+ Loads the |gnuplot| preset. By default, it uses the |pdf| terminal:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot}
+plot sin(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+
+You can also specify the gnuplot options to the pdf terminal, like the size, using:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot,pdf terminal={size 5cm,4cm}}
+plot sin(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+You can also change the options of the |includegraphics| command used to include the image, using as usual:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot,set includegraphics options={width=5cm,height=4cm}}
+plot sin(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+You can also use other terminals using the |set terminal| option. For instance, you can use the png terminal and configure its size using:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot,set terminal={png size 400,300}}
+plot sin(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+The tikz terminal is a bit special since we do not want to use |\includegraphics| but |\input| to include the file. You can use it like this, just make sure:
+\begin{itemize}
+\item to have gnuplot installed with lua support. With nix you can get it with:\\
+ |nix-shell -p '(gnuplot.override { withLua = true; })'|
+\item Add |\usepackage{gnuplot-lua-tikz}| after making sure to run\\
+ |gnuplot -e "set terminal tikz createstyle"| once to create the |.sty| file.
+\end{itemize}
+\begin{codeAndResult}
+% \usepackage{gnuplot-lua-tikz} %% Generate with gnuplot -e "set terminal tikz createstyle"
+\begin{CacheMeCode}{gnuplot,tikz terminal={size 5cm,4cm}}
+plot sin(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+(Note that if you do not provide any option to |tikz terminal|, it will just use the default value in gnuplot, you can also add any other option to the terminal here.) By default, we only cache the gnuplot compilation, but the |\input| is not cached (so gnuplot will not be run again the next time, but tikz will run every time). But it can also be cached, just add |cache tikz| for that:
+\begin{codeAndResult}
+\robExtConfigure{
+ add to preset={tikz}{
+ % Run gnuplot -e "set terminal tikz createstyle" in the robustExternalize folder first
+ % to create this file, or, better, run this command in your local folder and use
+ % "copy file to cache" to copy the 3 generated files.:
+ add to preamble={\usepackage{gnuplot-lua-tikz}},
+ },
+ add to preset={gnuplot}{
+ tikz terminal/.append style={
+ cache tikz,
+ },
+ },
+}
+\begin{CacheMeCode}{gnuplot, tikz terminal={size 8cm,5cm}}
+plot cos(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+We also automatically add |__ROBEXT_WAY_BACK__| to the |loadpath|, this way you do NOT need to type |plot "__ROBEXT_WAY_BACK__yourfile.dat"`| if the data is in the main folder. Note however that you need to add this file to the list of dependencies, otherwise it will not be recompiled if the file changes:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot, dependencies={gnuplot_data.dat}}
+plot "gnuplot_data.dat"
+\end{CacheMeCode}
+\end{codeAndResult}
+
+You can also use the current text width when using the tikz terminal using something like:\\
+|tikz terminal/.expanded={size \lenToCm{\textwidth},\lenToCm{.3\textwidth}}|\\
+Full example:
+\begin{codeAndResult}
+% Just to check size:
+\noindent\rule{\textwidth}{1mm}\\%
+\begin{CacheMeCode}{gnuplot, tikz terminal/.expanded={size \lenToCm{\textwidth},\lenToCm{.3\textwidth}}}
+plot cos(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+
+Similar to the tikz terminal, you can also use the |cairolatex| terminal like this:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot,cairolatex terminal}
+plot sin(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+As before, you can also specify the size, for instance it term of the current textwidth:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot, cairolatex terminal/.expanded={size \lenToCm{\textwidth},\lenToCm{.3\textwidth}}}
+plot cos(x)
+\end{CacheMeCode}
+\end{codeAndResult}
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \extractcommand\robExtGpgetvar\marg{variable name}\@@
+ \extractcommand\robExtGpgetvarNb\opt{*}\opt{\oarg{text, default 404}}\marg{variable name}\@@
+ \pgfmanualbody
+ Like |\gpgetvar{}| from |gnuplot-lua-tikz| but does not produce an error if the variable does not exist yet (mostly useful if you compile in parallel as shown \mylink{https://github.com/leo-colisson/robust-externalize/issues/17}{here}). The first time, you will get a message like:
+
+ \robExtGpgetvar{test_variable}
+
+ and later this will compile fine:
+\begin{codeAndResult}
+\begin{CacheMeCode}{gnuplot, tikz terminal={providevars test_variable}}
+test_variable = 5
+plot cos(test_variable * x) title "Test2"
+\end{CacheMeCode}
+Variable is \robExtGpgetvar{test_variable}.
+\end{codeAndResult}
+|\robExtGpgetvarNb| is similar, except that it prints a number 404 by default (useful if you use it in siunit) and is expandable (also \mylink{https://github.com/leo-colisson/robust-externalize/issues/17}{needed for siunit}). You can choose another text using the optional argument. The star version prints a warning in the log if the variable does not exist, but can only be used in LuaLaTeX:
+\begin{codeAndResult}
+Variable is \num[round-mode=figures,round-precision=3]{\robExtGpgetvarNb{non_existing_variable}}.
+\end{codeAndResult}
+Note that you will get a warning if the variable does not exist (yet?) only in LuaLaTeX as in other engines there is no \mylink{https://tex.stackexchange.com/questions/705299/print-message-in-expandable-macro/705304}{way to write in the log with an expandable function}.
+\end{pgfmanualentry}
+
+\subsubsection{TikZit}
+
+\mylink{https://tikzit.github.io/}{TikZit} is a software to produce \tikzname{} images via a graphical interface.
+
+\begin{pgfmanualentry}
+ \extractcommand\cacheTikzit\opt{\oarg{preset}}\@@
+ \extractcommand\cacheTikzitWithStyle\opt{\oarg{preset}}\marg{name of style file}\@@
+ \pgfmanualbody
+ (since v2.5) These command will automatically cache the |\tikzfig| command (and therefore also |\ctikzfig|). While |\cacheTikzit| will let you create the preset (named |tikzit| preset by default), |\cacheTikzitWithStyle| will automatically create the preset style for you, loading your style given as parameter:
+ \begin{codeexample}[vbox]
+ %%%%%%% In your preamble:
+ \cacheTikzitWithStyle{new_zxstyle.tikzstyles}
+
+ %%%%%%% In your document:
+ \tikzfig{demo} % figures/ is optional
+ \end{codeexample}
+ If you prefer to do it manually, you can do instead:
+ \begin{codeexample}[vbox]
+ %%%%%%% In your preamble:
+ \robExtConfigure{
+ % First, we copy the tikzit-related files to the cache:
+ copy file to cache={tikzit.sty},
+ copy file to cache={new_zxstyle.tikzstyles},
+ % We create the tikzit preset loaded by default:
+ new preset={tikzit}{
+ latex,
+ add to preamble={
+ \usepackage{tikzit}
+ \input{new_zxstyle.tikzstyles}
+ },
+ },
+ }
+ % Cache all tikzit figures:
+ \cacheTikzit
+
+ %%%%%%% In your document:
+ \tikzfig{figures/demo}
+ \end{codeexample}
+ \textbf{WARNING:} since the tikz picture uses |baseline| that relies on the current font size to vertically align the figure, and since we do not yet propagate the current font size to the cached picture (there are so many ways to configure the font in \LaTeX\dots{}), you should make sure that the |tikzit| preset sets the font size like in your main document, for instance via:
+ \begin{codeexample}[vbox]
+ %%%%%%% In your preamble:
+ \cacheTikzitWithStyle{new_zxstyle.tikzstyles}
+ \robExtConfigure{
+ add to preset={tikzit}{
+ add to latex options={12pt},
+ },
+ }
+ %%%%%%% In your document:
+ \tikzfig{demo} % figures/ is optional
+ \end{codeexample}
+ Note that |\tikzfig| accepts an additional optional argument for further options, for instance to forward locally a macro or to disable externalization:
+ \begin{codeexample}[vbox]
+ %%%%%%% In your preamble, make sure to load:
+ %% \usepackage{tikzit}
+ %% \input{new_zxstyle.tikzstyles}
+ %% if you want "disable externalization" to work.
+ \cacheTikzitWithStyle{new_zxstyle.tikzstyles}
+ %%%%%%% In your document:
+ \tikzfig<disable externalization>{demo} % figures/ is optional
+ \end{codeexample}
+\end{pgfmanualentry}
+
\subsubsection{Custom languages}
To add support to new languages, see \cref{sec:otherLanguages} for an example.
@@ -3632,10 +4292,19 @@ It might be handy to cache automatically a given environment: we already provide
to cache all tikz pictures (unless externalization is disabled), but we also provide tools to handle arbitrary environments.
\begin{pgfmanualentry}
- \extractcommand\robExtExternalizeAllTikzpicture\opt{\oarg{preset for tikz}}\opt{\oarg{preset for tikzpicture}}\opt{\oarg{delimiters}}\@@
+ \extractcommand\robExtExternalizeAllTikzpictures\opt{\oarg{preset for tikz}}\opt{\oarg{preset for tikzpicture}}\opt{\oarg{delimiters}}\@@
\extractcommand\cacheTikz\opt{\oarg{preset for tikz}}\opt{\oarg{preset for tikzpicture}}\opt{\oarg{delimiters}}\@@
+ \extractcommand\robExtDoNotExternalizeAllTikzpictures\@@
+ \extractcommand\doNotCacheTikz\@@
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/cache tikz\@nil
+ \extractkey/robExt/cache tikz\@nil
+ \extractkey/robExt/cache tikz 2 args=\marg{tikz preset}\marg{tikzpicture preset}\@nil
+ \extractkey/robExt/cache tikz 3 args=\marg{tikz preset}\marg{tikzpicture preset}\marg{delimiters cacheMe options}\@nil
+ \makeatother%
\pgfmanualbody
- This will automatically cache all tikz pictures (both are alias, |\cacheTizk| is available from v2.0). Since v2.0, we added the delimiters options and we allow to specify custom presets for |tikz| and |tikzpicture|, and we parse |\tikz| as well (the |tikz| preset is now used by |\tikz| by default while the |tikzpicture| preset is used by |tikzpicture|). Note that we add an additional optional argument to the tikz picture via its first argument delimited by |delimiters| (defaults to |<>|) to specify preset options, which can for instance be practical to disable externalization on individual pictures. Cf.\ \cref{sec:disableExternalization} to see an example of use.
+ (|cache tikz*| from 2.3, simply style alias) This will automatically cache all tikz pictures (the |*ExternalizeAllTikzpicturers| are alias of the |*cacheTikz| which is available from v2.0). Since v2.0, we added the delimiters options and we allow to specify custom presets for |tikz| and |tikzpicture|, and we parse |\tikz| as well (the |tikz| preset is now used by |\tikz| by default while the |tikzpicture| preset is used by |tikzpicture|). Note that we add an additional optional argument to the tikz picture via its first argument delimited by |delimiters| (defaults to |<>|) to specify preset options, which can for instance be practical to disable externalization on individual pictures. Cf.\ \cref{sec:disableExternalization} to see an example of use.
\begin{codeexample}[width=0pt,vbox]
\cacheTikz
@@ -3687,7 +4356,27 @@ You can also change the default style loaded for tikz and tikzpicture (note that
\node(A){In tikzpicture \hello};
\end{tikzpicture}
\end{codeexample}
+Note that the |cache tikz| styles (the variation just provide default values) is useful for instance if you only want to locally enable |cache tikz| for the |\input| of a style (this way you can cache the output of a cached thing\dots{}). For instance, |gnuplot| with a tikz terminal will compile into a tex file that will be inputted. But unless |\cacheTikz| is enabled, the inputted picture will not be cached (i.e. tikz will need to run). If you still want to cache it without enabling |\cacheTikz| globally, you can load this style in the |gnuplot| style, or do something like:
+
+|\doNotCacheTikz| just undo |\cacheTikz|:
+\begin{codeexample}[width=0pt,vbox]
+\def\whereIAm{(not cached)}
+\robExtConfigure{
+ add to preset={tikz}{
+ add to preamble={
+ \def\whereIAm{(cached)}
+ },
+ },
+}
+\cacheTikz
+\doNotCacheTikz
+
+\tikz \node[fill=pink, rounded corners]{\whereIAm};
+\begin{tikzpicture}
+ \node[fill=pink, rounded corners]{\whereIAm};
+\end{tikzpicture}
+\end{codeexample}
\end{pgfmanualentry}
\begin{pgfmanualentry}
@@ -3809,7 +4498,7 @@ Let us say that you want to cache all elements of a given environment, like |min
\end{pgfmanualentry}
\paragraph{Defining its own macro without repeating its definition.}
-Note that when you define yourself a macro function, the above structure might not be optimal as you need to define the macro in the main document (in case you disable the externalization) and in the template. One option to avoid repeated code is to write the definition in a common input file (see \cref{sec:dependencies}), but you might prefer to keep everything in a single file. In that case, you can simply wrap your function into |cacheMe| yourself. Say you want your function to draw a circle like, |\tikz \draw[fill=#2] (0,0) circle [radius=#1];|, then wrap in inside |CacheMe|:
+Note that when you define yourself a macro function, the above structure might not be optimal as you need to define the macro in the main document (in case you disable the externalization) and in the template. One option to avoid repeated code is to write the definition in a common input file (see \cref{sec:dependencies}), use |\runHereAndInPreambleOfCachedFiles| or |forward=\macroToExport|. But sometimes, you might need to do more involved operations, for instance to add a file as a dependency etc. So another solution it to wrap yourself your function into |cacheMe| yourself. Say you want your function to draw a circle like, |\tikz \draw[fill=#2] (0,0) circle [radius=#1];|, then wrap in inside |CacheMe|:
\begin{codeexample}[width=0mm,vbox]
% D<>{} is an optional argument enclosed in <>, we use this to pass arguments to CacheMe
@@ -3899,9 +4588,77 @@ bash JOBNAME-robExt-compile-missing-figures.sh
\subsection{How to debug}\label{sec:debug}
-If for some reasons you are unable to understand why a build fails, first check if you compiled your document with |-shell-escape| (not that this must appear \textbf{before} the filename). Then, you can look at the log file to get more advices: when a cached document is compiled, we always write the full compilation command before compiling the file in the log file. This way, you can easily check the content of the file and see why it fails to compile. The compilation errors are also displayed directly in the output, and you can read the log file for details.
+If for some reasons you are unable to understand why a build fails, first check if you compiled your document with |-shell-escape| (not that this must appear \textbf{before} the filename).
+
+Since v2.3, we provide a more advanced error handling system in order to provide more meaningful errors to the user, and to write the full compilation output in the log in case of an error. We do so by wrapping commands around something like |(my command) > somelog.tex 2>&1|; therefore nothing is printed on screen during the compilation of the cached picture, you only get a message if there is an error.
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/do not redirect compilation output\@nil
+ \makeatother
+ If you want to come back to the old behavior, that just runs the command is it either set this option, or set |\def\robExtDoNotRedirectOutput{}| and |\def\robExtDoNotRedirectOutputInManuallyCompileMissingFigures{}| (the last one will only concern commands written to the |robExt-compile-missing-figures.sh|, which is used in manual mode and in parallel mode).
+\end{pgfmanualentry}
+
+Starting from 2.3, we also automatically print an actual error message like:
+\begin{verbatim}
+! Package robExt Error: On line 20: the pdf file
+(robExt)
+robustExternalize/robExt-F27CD43D192AA2668A16DEAA616591FF.pdf
+(robExt) is not present. The compilation command "cd
+(robExt) robustExternalize/ && xelatex -halt-on-error
+(robExt) "robExt-F27CD43D192AA2668A16DEAA616591FF.tex"" used
+(robExt) to compile the environment on line 20 certainly
+(robExt) failed with errors:
+(robExt) vvvvvv
+(robExt) ! Package tikz Error: Giving up on this path. Did
+(robExt) you forget a semicolon?.
+(robExt)
+(robExt) ^^^^^^
+(robExt) See full logs below (you might need to press ENTER
+(robExt) to go to the next error) or in
+(robExt)
+robustExternalize/robExt-F27CD43D192AA2668A16DEAA616591FF-compilation.log.
+\end{verbatim}
+You can see inside the location in the main tex file of the block containing the error, we provide also the compilation command that lead to this error, and the lines of the log containing the word ``error'' (case insensitive), as well as the path to the full log of the compilation of the inner command, that you can also see if you continue the compilation by pressing Enter or by looking at the full log file, for instance in TeXstudio. This smaller message is often good enough in LaTeX, but usually not very good for languages that do not print the word ``error''. In that case, add to your preset:
-You might often get an error |! Missing $ inserted.|: this is typically when a placeholder was left unreplaced (e.g.\ you forgot to define it, import it, or you forgot to wrap a command in |\evalPlaceholder{}|): since \LaTeX{} is asked to typeset |__something__|, it thinks that you are trying to write a subscript, and asks you to start first the math mode.
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/print whole file in error message\@nil
+ \extractkey/robExt/do not print whole file in error message\@nil
+ \makeatother
+ (Add this only in preset, do NOT set it globally)
+ If you want to print the whole file in the small error message because you do not want to inspect the full log file, you can use the style |print whole file in error message|. This is enabled by default on the gnuplot, python and bash presets for instance, but disabled in \LaTeX{} has it makes little sense to print thousands of log lines in the error.
+\end{pgfmanualentry}
+
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/texstudio\@nil
+ \extractkey/robExt/logs should show as errors\@nil
+ \extractkey/robExt/prefix log message with=\marg{string to prepend to log message}\@nil
+ \extractkey/robExt/spacing between lines in log=\marg{content to separate lines in log}\@nil
+ \makeatother
+ Some IDE like TeXstudio will only print lines starting with an exclamation mark, assuming that they are spaced enough, so to make the compilation errors more visible in the log, we can start every line in the log with a |!| (you can set it globally via |logs should show as errors| that internally calls |prefix log message with|) and separate all lines with enough empty lines using |spacing between lines in log|. For simplicity, we create |texstudio| to automatically configure these values so that errors print nicely in texstudio via:
+\begin{verbatim}
+\robExtConfigure{texstudio}
+\end{verbatim}
+This way you will get errors like:
+\begin{verbatim}
+-------- We print now the full log --------
+! sh: ligne 1: gnuplot : commande introuvable
+-------- End of the full log --------
+\end{verbatim}
+and the line |sh: ligne 1: gnuplot : commande introuvable| will appear in your IDE without going in the log file. Note that this will only be printed for items that enable |print whole file in error message| not to pollute the errors space when the log contains many lines (e.g. \LaTeX{}), but this is automatically enabled on most default presets.
+\end{pgfmanualentry}
+
+Then, you can look at the log files\footnote{Either the latex one or the |-compilation.log| file, and sometimes try in a terminal if you really can't see any useful error as it might be the case that the error is not printed in the log file, which occurs for instance if xparse is not installed on Windows and you use the compilation command in parallel.} to get more advices, and run yourself the compilation command printed in the above error message. This way, you can easily check the content of the file and see why it fails to compile. In version before 2.3, or if you use |do not redirect compilation output|, the compilation errors are also displayed directly in the output, and you can read the log file for details.
+
+You might often get an error:
+\begin{verbatim}
+! Missing $ inserted.
+\end{verbatim}
+This is typically when a placeholder was left unreplaced (e.g.\ you forgot to define it, import it, or you forgot to wrap a command in |\evalPlaceholder{}|): since \LaTeX{} is asked to typeset |__something__|, it thinks that you are trying to write a subscript, and asks you to start first the math mode.
To get more advanced info during the compilation command, set the style |more logs| (that does |\def\robExtDebugMessage#1{\message{^^J[robExt] #1}}|) in order to print some messages on the replacement process (there is also |\robExtDebugWarning| for more important messages, but it prints the logs by default.
@@ -3948,6 +4705,15 @@ You can also use |debug| (or its alias |print command and source|) in order to d
Show all imported placeholders and their content. Use the start not to pause.
\end{pgfmanualentry}
+\begin{pgfmanualentry}
+ \makeatletter%
+ \def\extrakeytext{style, }
+ \extractkey/robExt/nb lines after error to show=\marg{nb lines to keep}\@nil
+ \extractkey/robExt/remove line number\@nil
+ \extractkey/robExt/do not remove line number\@nil
+ \makeatother
+ In order to make the small error message more meaningful (to avoid getting to the full log), we try to extract some errors automatically, reading lines staring with |!|, or containing |error| or |invalid|. But this line alone is often not enough, so you can use |nb lines after error to show| to determine the number of lines to show after (defaults to 3). |remove line number| will remove in the short error message any |l.| at the beginning of the line, otherwise some editors (at least emacs), will interpret it as a line number in the current file and will jump to a bad position (this is enabled by default). These options would work best if set globally when you use |compile in parallel|.
+\end{pgfmanualentry}
\subsection{Advanced optimizations}\label{sec:advancedOperations}
@@ -4006,36 +4772,58 @@ In order to know when to stop replacing placeholders earlier (i.e.\ without runn
If you disable the import mechanism (enabled by default), it will do an |\importAllPlaceholders| while evaluating the template. This is not recommended as it is quite inefficient, it is better to selectively import the group you need.
\end{pgfmanualentry}
-\begin{pgfmanualentry}
- \makeatletter%
- \def\extrakeytext{style, }
- \extractkey/robExt/disable optimizations\@nil
- \extractkey/robExt/enable optimizations\@nil
- \makeatother%
- \pgfmanualbody
-
-\end{pgfmanualentry}
+\section{Frequent errors}
+
+\subsection{Xelatex and tabs}
+It seems that xelatex (I never had issues with pdflatex and lualatex, but if you get this error on other engines you can try the same fix) \mylink{https://tex.stackexchange.com/a/14776/116348}{has a hard time dealing with tabs} if you do not compile with:
+\begin{verbatim}
+xelatex -8bit yourfile.tex
+\end{verbatim}
+If you see that tabs in your input file are turned into |^^I| in the source code, you should either add the |-8bit| option\dots{} or simply follow egreg's advice:
+\begin{center}
+ \emph{The strategy is very simple: never use TAB when dealing with TeX. Reserve the TAB key to trigger autocompletion and your life will be happier.}
+\end{center}
+If you use TeXstudio that uses Tabs by default, you can disable this feature by setting these two options:
+\begin{verbatim}
+Options > Configure TeXstudio > Editor > Replace indentation tabs with spaces
+Options > Configure TeXstudio > Editor > Replace tabs in text with spaces
+\end{verbatim}
\section{TODO and known bugs:}
\begin{itemize}
\item See how to deal with label, links and cite inside pictures (without disabling externalization). For label and links, I have a proof of concept, I ``just'' need to write it down. \url{https://tex.stackexchange.com/questions/695277/clickable-includegraphics-for-cross-reference-data}
\item Deal with remember picture
-\item Since externalizing is all about speed, it would be nice to do more benchmarks. But overall, it seems fairly optimized, at least when using the compiled presets.
-\item Add a way to forward tikz styles and/or arbitrary code.
-\item Create a more efficient/precise way to check if a word is present than string ``is in''. Indeed, for now for each color/... to export, we check if the string contains this word, which scales like $O(sn)$ where $s$ is the size of the string and $n$ is the number of colors etc to export. Instead, I'd like to run it in $O(s)$ by extracting all words a single time, and then checking if this word exists or not. This is not an issue for |\newcommandAutoforward|, but could be an issue when exporting many colors or |\genericAutoForward|.
+\item Since externalizing is all about speed, it would be nice to do more benchmarks. But overall, it seems fairly optimized, at least when using the compiled presets. One option to gain in term of efficiency and simplicity might be to directly use the fact that the placeholders start and end with two dashes: a more efficient implementation might be doable using something like |\def\findPlaceholders#1__#2__{}| instead of string replacement. I will try to investigate in future releases.
\end{itemize}
-\section{Acknowledgments}
-
-I am deeply indebted to many users on \url{tex.stackexchange.com} that made the writing of this library possible. I can't list you all, but thank you so much! A big thanks also to the project \url{https://github.com/sasozivanovic/memoize/} from which I borrowed most of the code to automatically wrap commands. Thanks to kiryph for providing useful feedbacks.
-
\section{Changelog}
\begin{itemize}
-\item Future v2.3 (master on github, not released yet on CTAN):
+\item v2.5:
+ \begin{itemize}
+ \item Add tikzit support
+ \item Add support for |--output-directory|
+ \end{itemize}
+\item v2.4:
+ \begin{itemize}
+ \item Better error message in wget if file not found
+ \item Add support for arXiv with |rename backup files for arxiv|, |print source when saving|, |backup source for arxiv|, |forward counter force value|
+ \item Add |\robExtMv|, |\robExtCp|, |set compilation command create if no error| and |set compilation command move if no error|.
+ \item Add |copy file to cache|
+ \end{itemize}
+\item v2.3:
+ \begin{itemize}
+ \item Fix bug in |more logs| and |less logs|
+ \item Make |if matches word| more efficient, independent on the number of runs, allowing registration, namespaces, etc.
+ \item Added |\definecolorAutoForward| and |\colorletAutoForward|
+ \item Add support for gnuplot
+ \item Added |\runHereAndInPreambleOfCachedFiles|
+ \item Clearer and more advanced error handling
+ \item Add support for online images with |\includegraphicsWeb|
+ \end{itemize}
\item v2.2
\begin{itemize}
\item v2.1 introduced two important bugs where hashes could not be used in a |\cacheMe| environment, and |auto forward| was not working if the string was containing an environment. This is fixed now.
@@ -4078,6 +4866,9 @@ I am deeply indebted to many users on \url{tex.stackexchange.com} that made the
\printindex
\end{document}
+% Luatex is needed, otherwise quotes ' are turned into another symbol in documentation
+% https://github.com/leo-colisson/robust-externalize/issues/11
% Local Variables:
-% TeX-command-extra-options: "-shell-escape -halt-on-error"
+% TeX-command-extra-options: "--shell-escape -halt-on-error"
+% TeX-engine: luatex
% End: \ No newline at end of file