diff options
-rw-r--r-- | Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.pdf | bin | 1634655 -> 1634999 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex | 6 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty | 172 |
3 files changed, 175 insertions, 3 deletions
diff --git a/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.pdf b/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.pdf Binary files differindex 92914f28333..afb803aa2c4 100644 --- a/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.pdf +++ b/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.pdf diff --git a/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex b/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex index 049cfb54432..ca511919896 100644 --- a/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex +++ b/Master/texmf-dist/doc/latex/robust-externalize/robust-externalize.tex @@ -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 @@ Options > Configure TeXstudio > Editor > Replace tabs in text with spaces \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. diff --git a/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty b/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty index 5deeec6c84b..a84155e474b 100644 --- a/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty +++ b/Master/texmf-dist/tex/latex/robust-externalize/robust-externalize.sty @@ -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 @@ if __name__ == '__main__': \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 @@ if __name__ == '__main__': 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,6 +3268,38 @@ if __name__ == '__main__': } \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,6 +3784,138 @@ print_file.close() \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" |