texlive[70653] Master/texmf-dist: robust-externalize (15mar24)
commits+karl at tug.org
commits+karl at tug.org
Fri Mar 15 22:24:25 CET 2024
Revision: 70653
https://tug.org/svn/texlive?view=revision&revision=70653
Author: karl
Date: 2024-03-15 22:24:25 +0100 (Fri, 15 Mar 2024)
Log Message:
-----------
robust-externalize (15mar24)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.pdf
trunk/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex
trunk/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty
Modified: trunk/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex 2024-03-15 21:24:13 UTC (rev 70652)
+++ trunk/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex 2024-03-15 21:24:25 UTC (rev 70653)
@@ -105,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.8}\\[3mm]
+ {Léo Colisson \quad Version 2.9}\\[3mm]
{\href{https://github.com/leo-colisson/robust-externalize}{\texttt{github.com/leo-colisson/robust-externalize}}}
\end{center}
@@ -4932,6 +4932,10 @@
\section{Changelog}
\begin{itemize}
+\item v2.9 (2024/03/15)
+ \begin{itemize}
+ \item Bug that may forbid the package to load has been fixed (you might encounter |ERROR: Missing = inserted for \ifnum|)
+ \end{itemize}
\item v2.8 (current master, not yet released):
\begin{itemize}
\item Fix a regression bug introduced in 2.7: |python print code and result| was adding a new line above the code printed. This is fixed now.
Modified: trunk/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty 2024-03-15 21:24:13 UTC (rev 70652)
+++ trunk/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty 2024-03-15 21:24:25 UTC (rev 70653)
@@ -1,4 +1,4 @@
-\ProvidesPackage{robust-externalize}[2.8 Cache anything (tikz, latex, python) in a robust, efficient and pure way.]
+\ProvidesPackage{robust-externalize}[2024/03/15 v2.9 Cache anything (tikz, latex, python) in a robust, efficient and pure way.]
% todo:
% change order argument replace from list, it is hard to read this way
@@ -251,6 +251,7 @@
\msg_new:nnn {robExt}{enabled parallel no shell escape}{Warning:~you~enabled~parallel~compilation~but~shell-escape~is~disabled.}
\msg_new:nnn {robExt}{rerun because parallel}{Warning:~Compiling~all~missing~figures~in~parallel~with~"#1".~You~need~to~rerun~LaTeX~to~include~them.}
\msg_new:nnn {robExt}{gpgetvar recompilation needed}{Warning:~you~need~to~recompile~as~the~gpgetvar~variable~"#1"~does~not~exist~yet.}
+\msg_new:nnn {robExt}{warning res not defined}{Warning:~the~result~\\res{#1}~is~not~defined,~maybe~try~to~recompile..}
% dummy placeholders added if image is not present
\def\robExtImagePlaceholderIfManualMode{
@@ -857,7 +858,7 @@
\NewDocumentCommand{\robExtPlaceholderFromString}{smm}{
- \str_set_eq:cN { l__robExt_placeholder_#2_str } {#3}
+ \str_set_eq:cN { l__robExt_placeholder_#2_str } #3
\checkIfPlaceholderNameIsLegal{#2}
\IfBooleanTF {#1} {} {\robExtAddPlaceholderToList{#2}}
}
@@ -2808,6 +2809,9 @@
recompile/.code={\def\robExtForceRecompilation{}},
do not recompile/.code={\let\robExtForceRecompilation\undefined},
set compilation command/.code={\robExtSetCompilationCommand{#1}},
+ change source extension/.style={
+ add before placeholder/.expanded={__ROBEXT_COMPILATION_COMMAND__}{\robExtCp\space "__ROBEXT_SOURCE_FILE__" "__ROBEXT_OUTPUT_PREFIX__.#1" &&},
+ },
% like "set compilation command" but moves the "__ROBEXT_OUTPUT_PDF__-tmp" to "__ROBEXT_OUTPUT_PDF__" if
% there is no error.
set compilation command move if no error/.style={
@@ -3264,7 +3268,39 @@
}
\let\cacheMe\robExtCacheMe
+\ExplSyntaxOn
%% #1: Arguments, #2: content to externalize
+\str_new:N \__robExt_tmp_contain_code_str
+\tl_new:N \__robExt_tmp_contain_code_tl
+\NewDocumentCommand{\robExtCacheMeCode}{O{}+v}{%
+ {% Group
+ %% We store the input in a non-string element for efficiently implementing "auto forward"
+ \edef\robExtUserInputCacheMe{\unexpanded{#2}}%
+ \tl_set:Nn \__robExt_tmp_contain_code_tl {#2}
+ \tl_replace_all:Nen \__robExt_tmp_contain_code_tl {\char_generate:nn{13}{12}} {^^J}
+ \str_set:Ne \__robExt_tmp_contain_code_str {\tl_to_str:e {\__robExt_tmp_contain_code_tl}}
+ %\str_show:N \__robExt_tmp_contain_code_str
+ %\tl_replace_all:Nnn \__robExt_tmp_contain_code_str {^^M} {b}
+ %\str_show:N \__robExt_tmp_contain_code_str
+ \pgfkeys{%
+ /robExt/.cd,%
+ %% This is needed notably if the cached elements are nested, like the include command uses itself a tikz
+ %% picture etc cached via \cacheTikz... It it hard to reset everything efficiently (like we might not
+ %% want to reset all compilation commands etc), so you can add here stuff that might need to be restored
+ %% later.
+ reset,
+ /utils/exec={\robExtPlaceholderFromString{__ROBEXT_MAIN_CONTENT_ORIG__}{\__robExt_tmp_contain_code_str}},
+ default~style,%
+ defaultPlaceholderFromCodeStyle,
+ #1,
+ }%
+ \robExtEvaluateCompileAndInclude%
+ }%
+}
+\let\cacheMeCode\robExtCacheMeCode
+\ExplSyntaxOff
+
+%% #1: Arguments, #2: content to externalize
\NewDocumentEnvironment{RobExtCacheMe}{m+b}{%
\robExtCacheMe[#1]{#2}%
}{}
@@ -3748,8 +3784,140 @@
\robExtCopyGroupPlaceholders{python print code result}{main}
\robExtRegisterGroupPlaceholders{python print code result}
+%%%%%%
+%%%%%% Group "python exec"
+%%%%%%
+\robExtClearGroupPlaceholders{main}
+
+% if we set res = XXX or res[""] = XXX it will print it by default, if we do instead res[42] = XXX
+% it will not load it. To make this easy to program, we create an element for the empty string,
+% this way we can always \res{} in the include command.
+
+\begin{RobExtPlaceholderFromCode}[remove spaces until=>]{__ROBEXT_PYTHON_EXEC_TEMPLATE__}
+ > def toMacro(x):
+ > if hasattr(x, '__toMacro'):
+ > return x.__toMacro()
+ > else:
+ > return str(x)
+ >
+ > __ROBEXT_PYTHON_EXEC_LIBRARY_CHANGES__
+ > __ROBEXT_PYTHON_EXEC_CUSTOM_TO_MACRO_DEF__
+ > # We create a special class extending dict to check if the user just did res[42] = xxx
+ > # or res = foo, as in that case we will just print the result directly.
+ > class DictToExportToMacros(dict):
+ > pass
+ > res = DictToExportToMacros()
+ > res[""] = ""
+ > __ROBEXT_PYTHON_EXEC_RES_EQUALITY____ROBEXT_MAIN_CONTENT_ORIG__
+ > if not isinstance(res, DictToExportToMacros):
+ > write_to_out(r"\gdef\robExtResMacro{" + toMacro(res) + r"}")
+ > else:
+ > for k in res:
+ > # We create a macro with csname to allow numbers in the name etc and parallel compilation
+ > write_to_out(r"\expandafter\gdef\csname robExtResMacro" + str(k) + r"\endcsname{" + toMacro(res[k]) + r"}")
+\end{RobExtPlaceholderFromCode}
+
+\robExtSetPlaceholder{__ROBEXT_PYTHON_EXEC_RES_EQUALITY__}{}
+\robExtSetPlaceholder{__ROBEXT_PYTHON_EXEC_LIBRARY_CHANGES__}{}
+\begin{RobExtPlaceholderFromCode}{__ROBEXT_PYTHON_EXEC_CUSTOM_TO_MACRO_DEF__}
+\end{RobExtPlaceholderFromCode}
+
+% Some macro always expect a number to work, and must be expandable
+\NewDocumentCommand{\robExtResForceNumber}{m}{%
+ \ifcsname robExtResMacro#1\endcsname%
+ \csname robExtResMacro#1\endcsname%
+ \else%
+ 404%
+ \fi%
+}
+
+\def\robExtNoResult#1{%
+ \textbf{??}%
+}
+\NewDocumentCommand{\robExtRes}{m}{%
+ \ifcsname robExtResMacro#1\endcsname%
+ \csname robExtResMacro#1\endcsname%
+ \else%
+ \msg_warning:nnx{robExt}{warning res not defined}{#1}%%
+ \robExtNoRes{#1}%
+ \fi%
+}
+\let\res\robExtRes
+
+\robExtConfigure{
+ new preset={python exec res}{
+ python,
+ % we do that so that custom include command does not pick the result from previous runs locally
+ /utils/exec={\let\robExtResMacro\undefined},
+ import placeholders={__ROBEXT_PYTHON_EXEC_CUSTOM_TO_MACRO_DEF__,__ROBEXT_PYTHON_EXEC_RES_EQUALITY__,__ROBEXT_PYTHON_EXEC_TEMPLATE__,__ROBEXT_PYTHON_EXEC_LIBRARY_CHANGES__},
+ custom include command={\robExtRes{}},
+ set placeholder={__ROBEXT_MAIN_CONTENT__}{__ROBEXT_PYTHON_EXEC_TEMPLATE__},
+ },
+ new preset={python exec}{
+ python exec res,
+ set placeholder={__ROBEXT_PYTHON_EXEC_RES_EQUALITY__}{res =},
+ },
+}
+
+\robExtCopyGroupPlaceholders{python exec}{main}
+\robExtRegisterGroupPlaceholders{python exec}
+
%%%%%%
+%%%%%% Group "sage" and "sage res"
+%%%%%%
+
+\robExtClearGroupPlaceholders{main}
+
+\robExtSetPlaceholder{__ROBEXT_SAGE_EXEC__}{sage}
+
+% We need to overwrite some definitions as it adds a .sage in front automatically by default
+\begin{RobExtPlaceholderFromCode}[]{__ROBEXT_SAGE_EXEC_LIBRARY_CHANGES__}
+def get_filename_from_extension(extension):
+ '''
+ If you want to create a file with extension 'extension' (with the appropriate base name), this command
+ is for you. For instance get_filename_from_extension(".mp4") would return something like
+ robExt-somehash.mp4
+ the extension can also be like get_filename_from_extension("-out.tex") etc.
+ '''
+ return os.path.join(get_cache_folder(), "__ROBEXT_OUTPUT_PREFIX__" + extension)
+
+ROBEXT_PLOT_SAVE_FORMAT = "png"
+ROBEXT_PLOT_SAVE_OPTIONS = {}
+ROBEXT_PLOT_ID = 0
+
+def __plot_graphics_to_macro(self):
+ global ROBEXT_PLOT_SAVE_FORMAT
+ global ROBEXT_PLOT_ID
+ global ROBEXT_PLOT_SAVE_OPTIONS
+ filename = get_file_base() + f"plot-{ROBEXT_PLOT_ID}.{ROBEXT_PLOT_SAVE_FORMAT}"
+ self.save(filename, **ROBEXT_PLOT_SAVE_OPTIONS)
+ ROBEXT_PLOT_ID += 1
+ return filename
+
+sage.plot.graphics.Graphics.__toMacro = __plot_graphics_to_macro
+
+\end{RobExtPlaceholderFromCode}
+
+\robExtConfigure{
+ new preset={sage res}{
+ python exec res,
+ import placeholders={__ROBEXT_SAGE_EXEC__,__ROBEXT_SAGE_EXEC_LIBRARY_CHANGES__},
+ set placeholder={__ROBEXT_PYTHON_EXEC_LIBRARY_CHANGES__}{__ROBEXT_SAGE_EXEC_LIBRARY_CHANGES__},
+ % Sage expects the extension .sage
+ set compilation command={__ROBEXT_SAGE_EXEC__ "__ROBEXT_OUTPUT_PREFIX__.sage"},
+ change source extension=sage,
+ },
+ new preset={sage}{
+ sage res,
+ set placeholder={__ROBEXT_PYTHON_EXEC_RES_EQUALITY__}{res =},
+ },
+}
+
+\robExtCopyGroupPlaceholders{python exec}{main}
+\robExtRegisterGroupPlaceholders{python exec}
+
+%%%%%%
%%%%%% Group "verbatim"
%%%%%%
More information about the tex-live-commits
mailing list.