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.