summaryrefslogtreecommitdiff
path: root/macros/generic/memoize/memoize.edtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/generic/memoize/memoize.edtx')
-rw-r--r--macros/generic/memoize/memoize.edtx760
1 files changed, 454 insertions, 306 deletions
diff --git a/macros/generic/memoize/memoize.edtx b/macros/generic/memoize/memoize.edtx
index 10794c7a3b..86ed2b6197 100644
--- a/macros/generic/memoize/memoize.edtx
+++ b/macros/generic/memoize/memoize.edtx
@@ -1,5 +1,3 @@
-% \iffalse
-%
% memoize.edtx (this is not a .dtx file; to produce a .dtx, process it with edtx2dtx)
%
%% This file is a part of Memoize, a TeX package for externalization of
@@ -21,8 +19,6 @@
%% The files belonging to this work and covered by LPPL are listed in
%% (<texmf>/doc/generic/memoize/)FILES.
%
-% \fi
-%
% \begin{macrocode}
%
% \relax
@@ -68,7 +64,7 @@
% listing options app={basicstyle=\ttfamily\scriptsize}}}
%
% \begin{tcbraster}[raster columns=100]
-% \tcbinputlisting{raster multicolumn=55, ins listing, top=1mm, bottom=1mm, title=memoize.ins,listing file=../memoize.ins, linerange={27-38}, leftupper=1mm}
+% \tcbinputlisting{raster multicolumn=55, ins listing, top=1mm, bottom=1mm, title=memoize.ins,listing file=../memoize.ins, linerange={27-39}, leftupper=1mm}
% \begin{tcboxedraster}[raster columns=1]{blankest, raster multicolumn=45}
% \tcbinputlisting{ins listing, title=advice.ins, listing file=../advice.ins, linerange=28-31}
% \tcbinputlisting{ins listing, title=collar\raisebox{0pt}[\height][0pt]{g}s.ins, listing file=../collargs.ins, linerange=29-31}
@@ -77,8 +73,7 @@
%
% Memoize also contains two scripts, |memoize-extract| and |memoize-clean|.
% Both come in two functionally equivalent implementations: Perl (|.pl|) and a
-% Python (|.py|). The code is listed in \S\ref{sec:code:scripts}, I believe it
-% is self-explanatory enough to lack more than a occasional comment.
+% Python (|.py|). Their code is listed in \S\ref{sec:code:scripts}.
%
%
% \thispagestyle{empty}
@@ -95,55 +90,55 @@
%
% \paragraph{Identification} of |memoize|, |memoizable| and |nomemoize|.
%<*mmz>
-%<latex>\ProvidesPackage{memoize}[2023/10/10 v1.0.0 Fast and flexible externalization]
+%<latex>\ProvidesPackage{memoize}[2024/1/02 v1.1.0 Fast and flexible externalization]
%<context>%D \module[
%<context>%D file=t-memoize.tex,
-%<context>%D version=1.0.0,
+%<context>%D version=1.1.0,
%<context>%D title=Memoize,
%<context>%D subtitle=Fast and flexible externalization,
%<context>%D author=Saso Zivanovic,
-%<context>%D date=2023-10-10,
+%<context>%D date=2024-01-02,
%<context>%D copyright=Saso Zivanovic,
%<context>%D license=LPPL,
%<context>%D ]
%<context>\writestatus{loading}{ConTeXt User Module / memoize}
%<context>\unprotect
%<context>\startmodule[memoize]
-%<plain>% Package memoize 2023/10/10 v1.0.0
+%<plain>% Package memoize 2024/01/02 v1.1.0
%</mmz>
%<*mmzable>
-%<latex>\ProvidesPackage{memoizable}[2023/10/10 v1.0.0 A programmer's stub for Memoize]
+%<latex>\ProvidesPackage{memoizable}[2024/1/02 v1.1.0 A programmer's stub for Memoize]
%<context>%D \module[
%<context>%D file=t-memoizable.tex,
-%<context>%D version=1.0.0,
+%<context>%D version=1.1.0,
%<context>%D title=Memoizable,
%<context>%D subtitle=A programmer's stub for Memoize,
%<context>%D author=Saso Zivanovic,
-%<context>%D date=2023-10-10,
+%<context>%D date=2024-01-02,
%<context>%D copyright=Saso Zivanovic,
%<context>%D license=LPPL,
%<context>%D ]
%<context>\writestatus{loading}{ConTeXt User Module / memoizable}
%<context>\unprotect
%<context>\startmodule[memoizable]
-%<plain>% Package memoizable 2023/10/10 v1.0.0
+%<plain>% Package memoizable 2024/01/02 v1.1.0
%</mmzable>
%<*nommz>
-%<latex>\ProvidesPackage{nomemoize}[2023/10/10 v1.0.0 A no-op stub for Memoize]
+%<latex>\ProvidesPackage{nomemoize}[2024/1/02 v1.1.0 A no-op stub for Memoize]
%<context>%D \module[
%<context>%D file=t-nomemoize.tex,
-%<context>%D version=1.0.0,
+%<context>%D version=1.1.0,
%<context>%D title=Memoize,
%<context>%D subtitle=A no-op stub for Memoize,
%<context>%D author=Saso Zivanovic,
-%<context>%D date=2023-10-10,
+%<context>%D date=2024-01-02,
%<context>%D copyright=Saso Zivanovic,
%<context>%D license=LPPL,
%<context>%D ]
%<context>\writestatus{loading}{ConTeXt User Module / nomemoize}
%<context>\unprotect
%<context>\startmodule[nomemoize]
-%<mmz>% Package nomemoize 2023/10/10 v1.0.0
+%<mmz>% Package nomemoize 2024/01/02 v1.1.0
%</nommz>
%
% \paragraph{Required packages} and \hologo{LaTeX}ization of \hologo{plainTeX}
@@ -163,13 +158,6 @@
\def\newtoks{\alloc@5\toks\toksdef\@cclvi}
\def\newwrite{\alloc@7\write\chardef\sixt@@n}
%</mmz&plain>
-% |Nomemoize| has to load |pgfopts| as well, and process package options (right
-% away, why not), otherwise \hologo{LaTeX} will complain.
-%<*latex>
-%<mmz,nommz>\RequirePackage{pgfopts} % pgfkeys-based package options
-%<nommz>\pgfkeys{/memoize/package options/.unknown/.code={}}
-%<nommz>\ProcessPgfPackageOptions{/memoize/package options}
-%</latex>
% I can't really write any code without |etoolbox| \dots
%<*mmz>
%<latex>\RequirePackage{etoolbox}
@@ -238,6 +226,7 @@
}%
}%
}
+%</mmz>
%
% In \hologo{ConTeXt}, |\unexpanded| means |\protected|, and the usual
% |\unexpanded| is available as |\normalunexpanded|. Option one: use dtx
@@ -249,6 +238,18 @@
% |\unexpanded| in the |.dtx|, and |sed| through the generated \hologo{ConTeXt}
% files to replace all its occurrences by |\normalunexpanded|. Oh yeah!
%
+% Load |pgfkeys| in |nomemoize| and |memoizable|. Not necessary in |memoize|,
+% as it is already loaded by CollArgs.
+%<*nommz,mmzable>
+%<latex>\RequirePackage{pgfkeys}
+%<plain>\input pgfkeys
+%<context>\input t-pgfkey
+%</nommz,mmzable>
+%
+% Different formats of |memoizable| merely load |memoizable.code.tex|, which
+% exists so that |memoizable| can be easily loaded by generic code, like a
+% |tikz| library.
+%<mmzable&!generic>\input memoizable.code.tex
%
% \paragraph.{Shipout}
% We will next load our own auxiliary package, CollArgs, but before we do
@@ -260,6 +261,7 @@
% section~\ref{sec:code:extern}. Below, we first check that the current
% meaning of |\shipout| is primitive, and then redefine it.
%
+%<*mmz>
%<*plain>
\def\mmz@regular@shipout{%
\global\advance\mmzRegularPages1\relax
@@ -284,7 +286,7 @@
% \paragraph.{Loading order} |memoize| and |nomemoize| are mutually exclusive,
% and |memoizable| must be loaded before either of them. |\mmz@loadstatus|: 1
% = memoize, 2 = memoizable, 3 = nomemoize.
-%<*(plain,context)&(mmz,nommz,mmzable)>
+%<*mmz,nommz>
\def\ifmmz@loadstatus#1{%
\ifnum#1=0\csname mmz@loadstatus\endcsname\relax
\expandafter\@firstoftwo
@@ -292,11 +294,9 @@
\expandafter\@secondoftwo
\fi
}
-%</(plain,context)&(mmz,nommz,mmzable)>
+%</mmz,nommz>
%<*mmz>
-%<latex>\@ifpackageloaded{nomemoize}%
-%<plain,context>\ifmmz@loadstatus{3}%
-{%
+\ifmmz@loadstatus{3}{%
\PackageError{memoize}{Cannot load the package, as "nomemoize" is already
loaded. Memoization will NOT be in effect}{Packages "memoize" and
"nomemoize" are mutually exclusive, please load either one or the other.}%
@@ -304,9 +304,7 @@
%<latex>\ProcessPgfPackageOptions{/memoize/package options}
\endinput
}{}%
-%<latex>\@ifpackageloaded{memoizable}%
-%<plain,context>\ifmmz@loadstatus{2}%
-{%
+\ifmmz@loadstatus{2}{%
\PackageError{memoize}{Cannot load the package, as "memoizable" is already
loaded}{Package "memoizable" is loaded by packages which support
memoization. Memoize must be loaded before all such packages. The
@@ -324,30 +322,20 @@
%<latex>\ProcessPgfPackageOptions{/memoize/package options}
\endinput
}{}%
-%<plain,context>\ifmmz@loadstatus{1}{\endinput}{}%
-%<plain,context>\def\mmz@loadstatus{1}%
+\ifmmz@loadstatus{1}{\endinput}{}%
+\def\mmz@loadstatus{1}%
%</mmz>
-%<*mmzable>
-%<latex>\@ifpackageloaded{memoize}%
-%<plain,context>\ifmmz@loadstatus{1}%
-{\endinput}{}
-%<latex>\@ifpackageloaded{nomemoize}%
-%<plain,context>\ifmmz@loadstatus{3}%
-{\endinput}{}%
-%<plain,context>\ifmmz@loadstatus{2}{\endinput}{}%
-%<plain,context>\def\mmz@loadstatus{2}%
-%</mmzable>
+%<*mmzable&generic>
+\ifcsname mmz@loadstatus\endcsname\endinput\fi
+\def\mmz@loadstatus{2}%
+%</mmzable&generic>
%<*nommz>
-%<latex>\@ifpackageloaded{memoize}
-%<plain,context>\ifmmz@loadstatus{1}%
-{%
+\ifmmz@loadstatus{1}{%
\PackageError{nomemoize}{Cannot load the package, as "memoize" is already
loaded; memoization will remain in effect}{Packages "memoize" and
"nomemoize" are mutually exclusive, please load either one or the other.}%
\endinput }{}%
-%<latex>\@ifpackageloaded{memoizable}%
-%<plain,context>\ifmmz@loadstatus{2}%
-{%
+\ifmmz@loadstatus{2}{%
\PackageError{nomemoize}{Cannot load the package, as "memoizable" is already
loaded}{Package "memoizable" is loaded by packages which support
memoization. (No)Memoize must be loaded before all such packages. The
@@ -363,8 +351,8 @@
of that package.}%
\endinput
}{}%
-%<plain,context>\ifmmz@loadstatus{3}{\endinput}{}%
-%<plain,context>\def\mmz@loadstatus{3}%
+\ifmmz@loadstatus{3}{\endinput}{}%
+\def\mmz@loadstatus{3}%
%</nommz>
%
%<*mmz>
@@ -373,7 +361,7 @@
% Read \hologo{TeX} file |#2| into token register |#1| (under the current
% category code regime); |\toksapp| is defined in CollArgs.
\def\filetotoks#1#2{%
- \immediate\openin0{#2}%
+ \immediate\mmz@openin0{#2}%
#1={}%
\loop
\unless\ifeof0
@@ -385,6 +373,12 @@
}
% \end{macro}
%
+% \begin{macro}{\mmz@openin,\mmz@openout}
+% A workaround for |morewrites|.
+\let\mmz@openin\openin
+\let\mmz@openout\openout
+% \end{macro}
+%
% \paragraph{Other} little things.
\newif\ifmmz@temp
\newtoks\mmz@temptoks
@@ -395,22 +389,24 @@
% \label{sec:code:configuration}
%
% \begin{macro}{\mmzset}
-% The user primarily interacts with |Memoize| through the |pgfkeys|-based
+% The user primarily interacts with Memoize through the |pgfkeys|-based
% configuration macro |\mmzset|, which executes keys in path |/mmz|. In
% |nomemoize| and |memoizable|, is exists as a no-op.
\def\mmzset#1{\pgfqkeys{/mmz}{#1}\ignorespaces}
%</mmz>
-%<nommz,mmzable>\def\mmzset#1{\ignorespaces}
+%<*nommz,mmzable&generic>
+\def\mmzset#1{\ignorespaces}
+%</nommz,mmzable&generic>
% \end{macro}
-%
-% \begin{macro}{\mmzset}
+%
+% \begin{macro}{\nommzkeys}
% Any |/mmz| keys used outside of |\mmzset| must be declared by this macro
% for |nomemoize| package to work.
%<mmz>\def\nommzkeys#1{}
-%<*nommz,mmzable>
+%<*nommz,mmzable&generic>
\def\nommzkeys{\pgfqkeys{/mmz}}
\pgfqkeys{/mmz}{.unknown/.code={\pgfkeysdef{\pgfkeyscurrentkey}{}}}
-%</nommz,mmzable>
+%</nommz,mmzable&generic>
% \end{macro}
%
% \begin{key}{enable, disable}
@@ -427,7 +423,9 @@
%
% |Nomemoize| does not need the keys themselves, but it does need the
% underlying conditional --- which will be always false.
-%<mmz,nommz,mmzable>\newif\ifmemoize
+%<*mmz,nommz,mmzable&generic>
+\newif\ifmemoize
+%</mmz,nommz,mmzable&generic>
%<*mmz>
\mmzset{%
enable/.style={begindocument/.append code=\memoizetrue},
@@ -439,10 +437,15 @@
% Memoize is enabled at the beginning of the document, unless explicitly
% disabled by the user in the preamble.
enable,
-}
% \end{macro}
% \end{key}
%
+% \begin{key}{options}
+% Execute the given value as a keylist of Memoize settings.
+ options/.style={#1},
+}
+% \end{key}
+%
% \begin{key}{normal,readonly,recompile}
% When Memoize is enabled, it can be in one of three modes
% (\MS\ref{sec:tut:working-on-a-picture}): normal, readonly, and recompile.
@@ -461,7 +464,7 @@
}
% \end{key}
%
-% \begin{key}{path, path/relative, path/dir, path/prefix}
+% \begin{key}{prefix}
% Key |path| executes the given keylist in path |/mmz/path|, to determine the
% full \emph{path prefix} to memo and extern files
% (\MS\ref{sec:tut:memodir},\ref{sec:memos}): |relative|, true by default,
@@ -471,56 +474,77 @@
% under user control, and neither is the suffix. These subkeys will be
% initialized a bit later, via |no memo dir|.
\mmzset{%
- path/.code={\pgfqkeys{/mmz/path}{#1}},
- path/.cd,
- relative/.is if=mmz@relativepath,
- dir/.store in=\mmz@dir,
- dir/.value required,
- prefix/.store in=\mmz@prefix,
- prefix/.value required,
-}
-\newif\ifmmz@relativepath
-% Key |path| concludes by performing two post-path-setting actions: creating
-% the given directory if |mkdir| is in effect, and noting the new path prefix
-% in record files (by eventually executing |record/prefix|, which typically
-% puts a |\mmzPrefix| line in the |.mmz| file). These actions are the reason
-% for having the path setting keys grouped under |path| --- we don't want them
-% to be triggered by changes of the individual components of the path.
-% Similarly, we don't want them triggered by multiple invocations of |path| in
-% the preamble; only the final setting matters, so |path| is only equipped with
-% the action-triggering code at the beginning of the document.
+ prefix/.code={\mmz@parse@prefix{#1}},
+}
+% \begin{macro}{\mmz@split@prefix}
+% This macro stores the detokenized expansion of |#1| into |\mmz@prefix|,
+% which it then splits into |\mmz@prefix@dir| and |\mmz@prefix@name| at the
+% final |/|. The slash goes into |\mmz@prefix@dir|. If there is no slash,
+% |\mmz@prefix@dir| is empty.
+\begingroup
+\catcode`\/=12
+\gdef\mmz@parse@prefix#1{%
+ \edef\mmz@prefix{\detokenize\expandafter{\expanded{#1}}}%
+ \def\mmz@prefix@dir{}%
+ \def\mmz@prefix@name{}%
+ \expandafter\mmz@parse@prefix@i\mmz@prefix/\mmz@eov
+}
+\gdef\mmz@parse@prefix@i#1/#2{%
+ \ifx\mmzeov#2%
+ \def\mmz@prefix@name{#1}%
+ \else
+ \appto\mmz@prefix@dir{#1/}%
+ \expandafter\mmz@parse@prefix@i\expandafter#2%
+ \fi
+}
+\endgroup
+% \end{macro}
+%
+% Key |prefix| concludes by performing two actions: it creates the given
+% directory if |mkdir| is in effect, and notes the new prefix in record files
+% (by eventually executing |record/prefix|, which typically puts a |\mmzPrefix|
+% line in the |.mmz| file). In the preamble, only the final setting of
+% |prefix| matters, so this key is only equipped with the action-triggering
+% code at the beginning of the document.
\mmzset{%
begindocument/.append style={
- path/.append code=\mmz@maybe@mkmemodir\mmz@record@prefix,
+ prefix/.append code=\mmz@maybe@mkmemodir\mmz@record@prefix,
},
- % Consequently, the post-path-setting actions must be triggered manually at
+ % Consequently, the post-prefix-setting actions must be triggered manually at
% the beginning of the document. Below, we trigger directory creation;
% |record/prefix| will be called from |record/begin|, which is executed at
% the beginning of the document, so it shouldn't be mentioned here.
begindocument/.append code=\mmz@maybe@mkmemodir,
}
-% Define the paths to the memo directory and the prefix.
-\def\mmz@dir@path{\ifmmz@relativepath.\fi/\mmz@dir}
-\def\mmz@prefix@path{\mmz@dir@path/\mmz@prefix}
% \end{key}
%
% \begin{key}{mkdir, mkdir command}
% Should we create the memo/extern directory if it doesn't exist? And which
-% command should we use to create it? Of course, shell escape must be
-% properly configured for this to work (\MS\ref{sec:shell-escape}).
-% ^^A todo: What about quoting the paths containing spaces on Windows? Will this work?
+% command should we use to create it? There is no initial value for the
+% latter, because |mkdir| cannot be executed out of the box, but note that
+% |extract=perl| and |extract=python| will set the extraction script with
+% option |--mkdir| as the value of |mkdir command|.
\mmzset{
mkdir/.is if=mmz@mkdir,
- mkdir command/.code={\def\mmz@mkdir@command##1{#1}},
- mkdir command={mkdir "#1"},
+ mkdir command/.store in=\mmz@mkdir@command,
+ mkdir command={},
}
% The underlying conditional \cs{ifmmz@mkdir} is only ever used in
% |\mmz@maybe@mkmemodir| below, which is itself only executed at the end of
-% |path| and in |begindocument|.
+% |prefix| and in |begindocument|.
\newif\ifmmz@mkdir
+\mmz@mkdirtrue
+% We only attempt to create the memo directory if |\ifmmz@mkdir| is in effect
+% and if both |\mmz@mkdir@command| and |\mmz@prefix@dir| are specified (i.e.\
+% non-empty).
\def\mmz@maybe@mkmemodir{%
\ifmmz@mkdir
- \pdf@system{\mmz@mkdir@command{\mmzOutputDirectory\mmz@dir@path}}%
+ \ifdefempty\mmz@mkdir@command{}{%
+ \ifdefempty\mmz@prefix@dir{}{%
+ \mmz@remove@quotes{\mmz@prefix@dir}\mmz@temp
+ \pdf@system{\mmz@mkdir@command\space"\mmz@temp"}%
+ }%
+ }%
\fi
}
% \end{key}
@@ -533,51 +557,49 @@
% filenames themselves have no prefix. Furthermore, |memo dir| triggers the
% creation of the directory.
\mmzset{%
- memo dir/.style={
- mkdir,
- path={
- relative,
- dir={#1.memo.dir},
- prefix={},
- },
- },
- memo dir/.default=\mmzUnquote\jobname,
- no memo dir/.style={
- mkdir=false,
- path={
- relative,
- dir={},
- prefix={#1.},
- },
- },
- no memo dir/.default=\mmzUnquote\jobname,
+ memo dir/.style={prefix={#1.memo.dir/}},
+ memo dir/.default=\jobname,
+ no memo dir/.style={prefix={#1.}},
+ no memo dir/.default=\jobname,
no memo dir,
}
% \end{key}
%
-% \begin{macro}{\mmzUnquote}
-% If the expanded argument is surrounded by double quotes, remove them. This
-% relies on |#1| containing no quotes other than the potential surrounding
-% quotes, which should be the case when applying the macro to |\jobname|. An
-% empty |#1| is dealt with correctly, even if |\jobname| can hardly ever be
-% empty (needs |openout_any=a|).
+% \begin{macro}{\mmz@remove@quotes}
+% This macro removes fully expands |#1|, detokenizes the expansion and then
+% removes all double quotes the string. The result is stored in the control
+% sequence given in |#2|.
%
% We use this macro when we are passing a filename constructed from
% |\jobname| to external programs.
-\def\mmzUnquote#1{\expanded{\noexpand\mmz@unquote#1}\mmz@unquote@end}
-\def\mmz@unquote#1{%
- \ifx\mmz@unquote@end#1%
+\def\mmz@remove@quotes#1#2{%
+ \def\mmz@remove@quotes@end{\let#2\mmz@temp}%
+ \def\mmz@temp{}%
+ \expanded{%
+ \noexpand\mmz@remove@quotes@i
+ \detokenize\expandafter{\expanded{#1}}%
+ "\noexpand\mmz@eov
+ }%
+}
+\def\mmz@remove@quotes@i{%
+ \CollectArgumentsRaw
+ {\collargsBraceCollectedfalse
+ \collargsNoDelimiterstrue
+ \collargsAppendPostwrap{{##1}}%
+ }%
+ {u"u\mmz@eov}%
+ \mmz@remove@quotes@ii
+}
+\def\mmz@remove@quotes@ii#1#2{%
+ \appto\mmz@temp{#1}%
+ \ifx&#2&%
+ \mmz@remove@quotes@end
+ \expandafter\@gobble
\else
- \ifx"#1%
- \expandafter\expandafter\expandafter\mmz@unquote@quotes
- \else
- \expandafter\expandafter\expandafter\mmz@unquote@noquotes
- \expandafter\expandafter\expandafter#1%
- \fi
+ \expandafter\@firstofone
\fi
+ {\mmz@remove@quotes@i#2\mmz@eov}%
}
-\def\mmz@unquote@quotes#1"\mmz@unquote@end{#1}
-\def\mmz@unquote@noquotes#1\mmz@unquote@end{#1}
% \end{macro}
%
% \begin{key}{ignore spaces}
@@ -832,6 +854,7 @@
%<context>\let\startmemoize\startnomemoize
%<context>\let\stopmemoize\stopnomemoize
%</nommz>
+%</mmz,nommz>
% \end{environment}
%
% \subsection{The memoization process}
@@ -843,6 +866,7 @@
% anywhere else. It is checked by |\Memoize| to prevent nested
% memoizations, deployed in advice run conditions set by |run only if
% memoizing|, etc.
+%<*mmz,nommz,mmzable&generic>
\newif\ifmemoizing
% \end{macro}
%
@@ -859,7 +883,7 @@
% An auxiliary macro which rescans the given
% code using |\scantokens| if the verbatim mode is active. We also need it
% in NoMemoize, to properly grab verbatim manually memoized code.
-%</mmz,nommz>
+%</mmz,nommz,mmzable&generic>
%<*mmz>
\def\mmz@maybe@scantokens{%
\ifmmz@verbatim
@@ -1091,15 +1115,16 @@
\gtoksapp\mmzCMemo{\global\mmzUnmemoizabletrue}%
\mmz@write@cmemo
\mmz@trace@endmemoize@unmemoizable
- \PackageWarning{memoize}{Marking this code as unmemoizable}%
+ \PackageInfo{memoize}{Marking this code as unmemoizable}%
\else
\ifmmz@abort
% If memoization was aborted, we create an empty c-memo, to make sure that
% no leftover c-memo tricks Memoize into thinking that the code was
% successfully memoized.
\mmz@trace@endmemoize@aborted
- \PackageWarning{memoize}{Memoization was aborted}%
- \mmz@write@empty@cmemo
+ \PackageInfo{memoize}{Memoization was aborted}%
+ \mmz@compute@context@mdfivesum
+ \mmz@write@cmemo
\else
% If memoization was not aborted, we compute the \meta{context md5sum},
% open and write out the memos, and shipout the externs (as pages into the
@@ -1320,7 +1345,7 @@
%
% \paragraph.{Tracing} We populate the hooks which send the tracing info to the
% terminal.
-\def\mmz@trace#1{\immediate\write16{[tracing memoize] #1}}
+\def\mmz@trace#1{\advice@typeout{[tracing memoize] #1}}
\def\mmz@trace@context{\mmz@trace{\space\space
Context: "\expandonce{\mmz@context@key}" --> \mmz@context@mdfivesum}}
\def\mmz@trace@Memoize@on{%
@@ -1424,9 +1449,6 @@
% \end{macro}
% \end{key}
%
-%</mmz>
-%<nommz,mmzable>\newcommand\IfMemoizing[2][]{\@secondoftwo}
-%<*mmz>
%
% \subsection{Context}
% \label{sec:code:context}
@@ -1465,24 +1487,27 @@
% context, key value to context, /handlers/.meaning to context,
% /handlers/.value to context}
% Utilities to put the meaning of various stuff into |context|.
+ % \indentmacrocode
meaning to context/.code={\forcsvlist\mmz@mtoc{#1}},
- csname meaning to context/.code={\mmz@mtoc@cs{#1}},
- key meaning to context/.code={\forcsvlist\mmz@mtoc\mmz@mtoc@keycmd{#1}},
+ csname meaning to context/.code={\mmz@mtoc@csname{#1}},
+ key meaning to context/.code={%
+ \forcsvlist\mmz@mtoc\mmz@mtoc@keycmd{#1}},
key value to context/.code={\forcsvlist\mmz@mtoc@key{#1}},
- /handlers/.meaning to context/.code={%
- \expanded{\noexpand\mmz@mtoc@cs{pgfk@\pgfkeyscurrentpath/.@cmd}}},
+ /handlers/.meaning to context/.code={\expanded{%
+ \noexpand\mmz@mtoc@csname{pgfk@\pgfkeyscurrentpath/.@cmd}}},
/handlers/.value to context/.code={%
- \expanded{\noexpand\mmz@mtoc@cs{pgfk@\pgfkeyscurrentpath}}},
+ \expanded{\noexpand\mmz@mtoc@csname{pgfk@\pgfkeyscurrentpath}}},
}
+% \noindentmacrocode
\def\mmz@mtoc#1{%
\collargs@cs@cases{#1}%
{\mmz@mtoc@cmd{#1}}%
{\mmz@mtoc@error@notcsorenv{#1}}%
{%
- \mmz@mtoc@cs{%
+ \mmz@mtoc@csname{%
%<context>start%
#1}%
- \mmz@mtoc@cs{%
+ \mmz@mtoc@csname{%
%<latex,plain>end%
%<context>stop%
#1}%
@@ -1492,17 +1517,18 @@
\begingroup
\escapechar=-1
\expandafter\endgroup
- \expandafter\mmz@mtoc@cs\expandafter{\string#1}%
+ \expandafter\mmz@mtoc@csname\expandafter{\string#1}%
}
-\def\mmz@mtoc@cs#1{%
+\def\mmz@mtoc@csname#1{%
\pgfkeysvalueof{/mmz/context/.@cmd}%
- \expandafter\string\csname#1\endcsname={\expandafter\meaning\csname#1\endcsname}%
- \pgfeov
+ \detokenize{#1}={\expandafter\meaning\csname#1\endcsname}%
+ \pgfeov
}
-\def\mmz@mtoc@key#1{\mmz@mtoc@cs{pgfk@#1}}
-\def\mmz@mtoc@key#1{\mmz@mtoc@cs{pgfk@#1/.@cmd}}
+\def\mmz@mtoc@key#1{\mmz@mtoc@csname{pgfk@#1}}
+\def\mmz@mtoc@keycmd#1{\mmz@mtoc@csname{pgfk@#1/.@cmd}}
\def\mmz@mtoc@error@notcsorenv#1{%
- \PackageError{memoize}{'\detokenize{#1}' passed to key 'meaning to context' is neither a command nor an environment}{}%
+ \PackageError{memoize}{'\detokenize{#1}' passed to key 'meaning to context'
+ is neither a command nor an environment}{}%
}
% \end{key}
%
@@ -1512,7 +1538,7 @@
%
% \paragraph{The path} to a c-memo consists of the path prefix, the MD5 sum of
% the memoized code, and suffix |.memo|.
-\def\mmz@cmemo@path{\mmz@prefix@path\mmz@code@mdfivesum.memo}
+\def\mmz@cmemo@path{\mmz@prefix\mmz@code@mdfivesum.memo}
% \begin{macro}{\mmzCMemo}
% The additional, free-form content of the c-memo is collected in this token
% register.
@@ -1536,7 +1562,7 @@
% |\mmzCMemo|.
\def\mmz@write@cmemo{%
% Open the file for writing.
- \immediate\openout\mmz@out{\mmz@cmemo@path}%
+ \immediate\mmz@openout\mmz@out{\mmz@cmemo@path}%
% The memo starts with the |\mmzMemo| marker (a signal that the memo is valid).
\immediate\write\mmz@out{\noexpand\mmzMemo}%
% We store the content of |\mmzContextExtra| by writing out a command that
@@ -1559,17 +1585,6 @@
}
% \end{macro}
%
-% \begin{macro}{\mmz@write@empty@cmemo}
-% This macro is used to create an empty c-memo on aborted memoization, to
-% make sure that no leftover c-memo tricks Memoize into thinking that the
-% code was successfully memoized.
-\def\mmz@write@empty@cmemo{%
- \immediate\openout\mmz@out{\mmz@cmemo@path}%
- \immediate\closeout\mmz@out
-}
-% \end{macro}
-%
-%
% \begin{macro}{\mmzSource}
% The c-memo memoized code marker. This macro is synonymous with |\endinput|,
% so the source following it is ignored when inputting the c-memo.
@@ -1644,7 +1659,7 @@
% hyphen-separated MD5 sums of the memoized code and the (evaluated) context,
% and suffix |.memo|.
\def\mmz@ccmemo@path{%
- \mmz@prefix@path\mmz@code@mdfivesum-\mmz@context@mdfivesum.memo}
+ \mmz@prefix\mmz@code@mdfivesum-\mmz@context@mdfivesum.memo}
%
% \paragraph{The structure} of a cc-memo:
% \begin{itemize}
@@ -1699,7 +1714,7 @@
% memoized code can update the context. This is one of the two reasons why
% we couldn't write the cc-memo directly into the file, but had to collect
% its contents into token register |\mmzCCMemo|.
- \immediate\openout\mmz@out{\mmz@ccmemo@path}%
+ \immediate\mmz@openout\mmz@out{\mmz@ccmemo@path}%
% Token register |\mmz@ccmemo@resources| consists of calls to
% |\mmz@ccmemo@append@resource|, so the following code writes down the list
% of created externs into the cc-memo. Wanting to have this list at the top
@@ -1751,7 +1766,7 @@
% might be produced by a failed \hologo{TeX}-based extraction, should count
% as no file. The |0| behind |\ifnum| is there because |\pdffilesize|
% returns an empty string when the file does not exist.
- \ifnum0\pdf@filesize{\mmz@dir@path/#1}=0
+ \ifnum0\pdf@filesize{\mmz@prefix@dir/#1}=0
\ifmmz@direct@ccmemo@input
\let\mmzMemo\endinput
\else
@@ -1768,8 +1783,10 @@
%
% \begin{macro}{\mmz@process@ccmemo,\mmzThisContext,\mmzEndMemo}
% This macro processes the cc-memo.
+% \indentmacrocode
\def\mmz@process@ccmemo{%
\mmz@trace@process@ccmemo
+ % \noindentmacrocode
% The following conditional signals whether cc-memo was successfully
% utilized. If the cc-memo file does not exist, |\ifmmz@abort| will remain
% true. If it exists, it is headed by the list of resources. If a
@@ -1865,11 +1882,11 @@
% full path.
\newcount\mmz@seq
\def\mmz@extern@basename{%
- \mmz@prefix\mmz@code@mdfivesum-\mmz@context@mdfivesum
+ \mmz@prefix@name\mmz@code@mdfivesum-\mmz@context@mdfivesum
\ifnum\mmz@seq>0 -\the\mmz@seq\fi
}
\def\mmz@extern@name{\mmz@extern@basename.pdf}
-\def\mmz@extern@basepath{\mmz@dir@path/\mmz@extern@basename}
+\def\mmz@extern@basepath{\mmz@prefix@dir\mmz@extern@basename}
\def\mmz@extern@path{\mmz@extern@basepath.pdf}
%
% \begin{key}{padding left, padding right, padding top, padding bottom}
@@ -2124,12 +2141,14 @@
% |\mmzExternPages| holds the number of shipped-out extern pages; and
% |\mmzExtraPages| holds, or at least should hold, the number of pages
% shipped out using any other means.
- \edef\pagenumber{\the\numexpr\mmzRegularPages
+ \edef\pagenumber{%
+ \the\numexpr\mmzRegularPages
% In \hologo{LaTeX}, the |\mmzRegularPages| holds to number of pages
% already shipped out. In \hologo{ConTeXt}, the counter is already
% increased while processing the page, so we need to subtract $1$.
%<context> -1%
- +\mmzExternPages+\mmzExtraPages}%
+ +\mmzExternPages+\mmzExtraPages
+ }%
% Record the creation of the new extern. We do this after shipping out the
% extern page, so that the recording mechanism can serve as an after-shipout
% hook, for the unlikely situation that some package really needs to do
@@ -2212,7 +2231,7 @@
enddocument/afterlastpage/.append code={%
\ifnum\mmzExternPages>0
\PackageWarning{memoize}{The compilation produced \the\mmzExternPages\space
- new extern\ifnum\mmzExternPages>1 s\fi.}%
+ new extern\ifnum\mmzExternPages>1 s\fi}%
\fi
},
}
@@ -2304,13 +2323,13 @@
%
% \begin{macro}{\mmz@include@extern@from@tbe@box}
% Include the extern number |#1| residing in |\mmz@tbe@box| into the
-% document. This helper macro makes it possible for a complex memoization
-% driver to process the cc-memo right after memoization --- by using the
-% |\mmzkeepexternstrue\xtoksapp\mmzAfterMemoizationExtra{\the\mmzCCMemo}|
-% trick --- to ensure that the result of the memoizing compilation matches
-% the result of inputting the cc-memo. The rest of the arguments are
-% gobbled, as we don't have to do any size adjustment or checking here, and
-% the box is of the correct type.
+% document. It may be called as |\mmzIncludeExtern| from |after memoization|
+% hook if |\ifmmzkeepexterns| was set to true during memoization. The macro
+% takes the same arguments as |\mmzIncludeExtern| but disregards all but
+% the first one, the extern sequential number. Using this macro, a complex
+% memoization driver can process the cc-memo right after memoization, by
+% issuing
+% |\global\mmzkeepexternstrue\xtoksapp\mmzAfterMemoizationExtra{\the\mmzCCMemo}|.
\def\mmz@include@extern@from@tbe@box#1#2#3#4#5#6#7#8#9{%
\setbox0\vbox{%
\@tempcnta#1\relax
@@ -2344,7 +2363,7 @@
\mmzset{
extract/.estore in=\mmz@extraction@method,
extract/.value required,
- begindocument/.append style={extract/.code=\mmz@preamble@only@warning},
+ begindocument/.append style={extract/.code=\mmz@preamble@only@error},
% \end{key}
%
% \begin{key}{extract/perl, extract/python}
@@ -2352,10 +2371,10 @@
% Memoize ships with two extraction scripts, a Perl script and a Python
% script, which are selected by |extract=perl| (the default) and
% |extract=python|, respectively. We run the scripts in verbose mode
- % (without |-q|), and keep the |.mmz| file as is, i.e.\ we're not commenting
- % out the |\mmzNewExtern| lines, because we're about to overwrite it
- % anyway. We also request the log file, which will contain
- % |\mmzExtractionSuccessful| if extraction was successful.
+ % (without |-q|), and keep the |.mmz| file as is (without |-k|), i.e.\
+ % we're not commenting out the |\mmzNewExtern| lines, because we're about
+ % to overwrite it anyway. We inform the script about the format of the
+ % document (|-F|).
extract/perl/.code={%
\mmz@clear@extraction@log
\pdf@system{%
@@ -2363,17 +2382,14 @@
\mmzvalueof{perl extraction options}%
}%
\mmz@check@extraction@log{perl}%
- \def\mmz@mkdir@command##1{\mmzvalueof{perl extraction command}\space --mkdir "##1"}%
+ \def\mmz@mkdir@command{\mmzvalueof{perl extraction command} --mkdir}%
},
perl extraction command/.initial=memoize-extract.pl,
- perl extraction options/.initial={%
-% \begin{listingregion}{perl-extraction-options.tex}
- -e -l "\mmzOutputDirectory\mmzUnquote\jobname.mmz.log" -w
- %<latex>"\string\PackageWarning{memoize (perl-based extraction)}{\string\warningtext}"
- %<plain>"\string\warning{memoize (perl-based extraction): \string\warningtext}"
- %<context>"\string\warning{memoize (perl-based extraction): \string\warningtext}"
- "\mmzOutputDirectory\mmzUnquote\jobname.mmz"
-% \end{listingregion}
+ perl extraction options/.initial={\space
+ %<latex>-F latex
+ %<plain>-F plain
+ %<context>-F context
+ \jobname\space
},
extract=perl,
extract/python/.code={%
@@ -2383,21 +2399,20 @@
\mmzvalueof{python extraction options}%
}%
\mmz@check@extraction@log{python}%
- \def\mmz@mkdir@command##1{\mmzvalueof{python extraction command}\space --mkdir "##1"}%
+ \def\mmz@mkdir@command{\mmzvalueof{python extraction command} --mkdir}%
},
python extraction command/.initial=memoize-extract.py,
- python extraction options/.initial={%
- -e -l "\mmzOutputDirectory\mmzUnquote\jobname.mmz.log" -w
- %<latex>"\string\PackageWarning{memoize (python-based extraction)}{\string\warningtext}"
- %<plain>"\string\warning{memoize (python-based extraction): \string\warningtext}"
- %<context>"\string\warning{memoize (python-based extraction): \string\warningtext}"
- "\mmzOutputDirectory\mmzUnquote\jobname.mmz"
+ python extraction options/.initial={\space
+ %<latex>-F latex
+ %<plain>-F plain
+ %<context>-F context
+ \jobname\space
},
}
-\def\mmz@preamble@only@warning{%
- \PackageWarning{memoize}{%
+\def\mmz@preamble@only@error{%
+ \PackageError{memoize}{%
Ignoring the invocation of "\pgfkeyscurrentkey".
- This key may only be executed in the preamble}%
+ This key may only be executed in the preamble}{}%
}
% \end{key}
%
@@ -2406,15 +2421,14 @@
% communicate with the system command via the ``extraction log file,'' produced
% by both \hologo{TeX}-based extraction and the Perl and Python extraction
% script. This file signals whether the embedded extraction was successful ---
-% if it is, the file contains |\mmzExtractionSuccessful| --- and also contains
-% any size-mismatch warnings (these are currently only thrown by the
-% \hologo{TeX}-based extraction). As the log is really a \hologo{TeX} file,
-% the idea is to simply input it after extracting each extern (for
+% if it is, the file ends if |\endinput| --- and also contains any warnings and
+% errors thrown by the script. As the log is really a \hologo{TeX} file, the
+% idea is to simply input it after extracting each extern (for
% \hologo{TeX}-based extraction) or after the extraction of all externs (for
% the external scripts).
\def\mmz@clear@extraction@log{%
\begingroup
- \immediate\openout0{\mmzUnquote\jobname.mmz.log"}%
+ \immediate\mmz@openout0{\jobname.mmz.log}%
\immediate\closeout0
\endgroup
}
@@ -2426,9 +2440,11 @@
\@input{\jobname.mmz.log}%
\ifmmz@temp \else \mmz@extraction@error \fi \endgroup }
\def\mmz@extraction@error{%
- \PackageWarning{memoize}{Extraction of externs from document "\mmzUnquote\jobname.pdf"
- using method "\extractionmethod" was unsuccessful. Have you set the
- shell escape mode as suggested in chapter 1 of the manual?}{}}
+ \PackageError{memoize}{Extraction of externs from document
+ "\jobname.pdf" using method "\extractionmethod" was
+ unsuccessful}{The extraction script "\mmzvalueof{\extractionmethod\space
+ extraction command}" wasn't executed or didn't finish execution
+ properly.}}
%
% \subsection{The record files}
% \label{sec:code:record}
@@ -2451,7 +2467,7 @@
% surely occurs at the top of the |.mmz| file. Listing each prefix type
% separately in this hook ensures that |prefix| of a certain type is
% executed after that type's |begin|.
- /mmz/record/#1/prefix/.try/.expanded=\mmz@prefix@path,
+ /mmz/record/#1/prefix/.try/.expanded=\mmz@prefix,
},
record/prefix/.append style={/mmz/record/#1/prefix/.try={##1}},
record/new extern/.append style={/mmz/record/#1/new extern/.try={##1}},
@@ -2495,7 +2511,7 @@
% We define this macro because |\aftergroup|, used in |record/prefix|, only
% accepts a token.
\def\mmz@record@prefix{%
- \mmzset{/mmz/record/prefix/.expanded=\mmz@prefix@path}%
+ \mmzset{/mmz/record/prefix/.expanded=\mmz@prefix}%
}
% \paragraph{Initialize} the hook keys, preactivate |mmz| record type, and
% execute hooks |begin| and |end| at the edges of the document.
@@ -2516,12 +2532,11 @@
% contains are intentionally as simple as possible (just a macro plus braced
% arguments), to facilitate parsing by the external scripts.
%
-% These hooks simply put the calls of the corresponding macros into the file.
-% All but hooks but |begin| and |end| receive the full path to the relevant
-% file as the only argument (ok, |prefix| receives the full path prefix, as set
-% by key |path|).
-%
% \begin{key}{record/mmz/...}
+% These hooks simply put the calls of the corresponding macros into the file.
+% All but hooks but |begin| and |end| receive the full path to the relevant
+% file as the only argument (ok, |prefix| receives the full path prefix, as
+% set by key |path|).
\mmzset{
record/mmz/begin/.code={%
\newwrite\mmz@mmzout
@@ -2529,7 +2544,7 @@
% location (the current directory, i.e.\ the directory where \hologo{TeX}
% is executed from; usually, this will be the directory containing the
% \hologo{TeX} source).
- \immediate\openout\mmz@mmzout{\jobname.mmz}%
+ \immediate\mmz@openout\mmz@mmzout{\jobname.mmz}%
},
% The |\mmzPrefix| is used by the clean-up script, which will remove all
% files with the given path prefix but (unless called with |--all|) those
@@ -2592,7 +2607,7 @@
% \begin{key}{record/sh/...} Define the Linux shell script record type.
record/sh/begin/.code={%
\newwrite\mmz@shout
- \immediate\openout\mmz@shout{\mmz@shname}%
+ \immediate\mmz@openout\mmz@shout{\mmz@shname}%
},
record/sh/new extern/.code={%
\begingroup
@@ -2611,7 +2626,7 @@
% Rinse and repeat for Windows.
record/bat/begin/.code={%
\newwrite\mmz@batout
- \immediate\openout\mmz@batout{\mmz@batname}%
+ \immediate\mmz@openout\mmz@batout{\mmz@batname}%
},
record/bat/new extern/.code={%
\begingroup
@@ -2649,7 +2664,7 @@
% variables |.DEFAULT_GOAL| and |.PHONY|.
\newwrite\mmz@makefileout
\newtoks\mmz@makefile@externs
- \immediate\openout\mmz@makefileout{\mmz@makefilename}%
+ \immediate\mmz@openout\mmz@makefileout{\mmz@makefilename}%
\immediate\write\mmz@makefileout{.DEFAULT_GOAL = externs}%
\immediate\write\mmz@makefileout{.PHONY: externs}%
},
@@ -2693,11 +2708,10 @@
}
% \end{key}
%
-% \begingroup
-% \setlength\MacroIndent{2em}
% \begin{macro}{\mmzUsedCMemo,\mmzUsedCCMemo,\mmzUsedExtern,\mmzNewCMemo,\mmzNewCCMemo,\mmzPrefix}
% We can ignore everything but |\mmzNewExtern|s. All these macros receive a
% single argument.
+% \indentmacrocode
\def\mmzUsedCMemo#1{}
\def\mmzUsedCCMemo#1{}
\def\mmzUsedExtern#1{}
@@ -2705,7 +2719,6 @@
\def\mmzNewCCMemo#1{}
\def\mmzPrefix#1{}
% \end{macro}
-% \endgroup
%
% \begin{macro}{\mmzNewExtern}
% Command |\mmzNewExtern| takes four arguments. It instructs us to extract
@@ -2744,11 +2757,11 @@
% \end{macro}
\def\mmz@pageextraction@error{%
\PackageError{memoize}{Extraction of extern page \pagenumber\space from
- document "\mmzUnquote\jobname.pdf" using method "\extractionmethod" was unsuccessful.
- Have you set the shell escape mode as suggested in chapter 1 of the
- manual?}{If "\mmzvalueof{tex extraction command}" was executed,
- shell escape mode is not the problem, and inspecting "\externbasepath.log"
- might give you a clue what's wrong}}
+ document "jobname.pdf" using method "\extractionmethod" was
+ unsuccessful.}{Check the log file to see if the extraction script was
+ executed at all, and if it finished successfully. You might also want to
+ inspect "\externbasepath.log", the log file of the embedded TeX compilation
+ which ran the extraction script}}
%
% \begin{key}{tex extraction command, tex extraction options, tex extraction script}
% Using these keys, we set the system call
@@ -2786,12 +2799,11 @@
-halt-on-error
-interaction=batchmode
-jobname "\externbasepath"
- \ifdefempty\mmzOutputDirectory{}{-output-directory "\mmzOutputDirectory"}
% \end{listingregion}
},
tex extraction script/.initial={%
% \begin{listingregion}{tex-extraction-script.tex} ^^A todo: context
- \def\noexpand\fromdocument{"\mmzOutputDirectory"\jobname.pdf}%
+ \def\noexpand\fromdocument{\jobname.pdf}%
\def\noexpand\pagenumber{\pagenumber}%
\def\noexpand\expectedwidth{\expectedwidth}%
\def\noexpand\expectedheight{\expectedheight}%
@@ -3008,6 +3020,7 @@
%<plain,context>noop/.style={inner handler=\mmz@auto@noop},
nomemoize/.style={noop, options=disable},
replicate/.style={run if memoizing, inner handler=\mmz@auto@replicate},
+ to context/.style={run if memoizing, outer handler=\mmz@auto@tocontext},
}
%
% \paragraph{Abortion}
@@ -3221,6 +3234,27 @@
}
% \end{macro}
% \end{mmzautokey}
+%
+% \begin{mmzautokey}{to context}
+% \begin{macro}{\mmz@auto@tocontext}
+% This outer handler appends the original definition of the handled command
+% to the context. The |\expandafter| are there to expand |\AdviceName|
+% once before fully expanding |\AdviceGetOriginalCsname|.
+\def\mmz@auto@tocontext{%
+ \expanded{%
+ \noexpand\pgfkeysvalueof{/mmz/context/.@cmd}%
+ original "\AdviceNamespace" csname "\AdviceCsname"={%
+ \noexpand\expanded{%
+ \noexpand\noexpand\noexpand\meaning
+ \noexpand\AdviceCsnameGetOriginal{\AdviceNamespace}{\AdviceCsname}%
+ }%
+ }%
+ }%
+ \pgfeov
+ \AdviceOriginal
+}
+% \end{macro}
+% \end{mmzautokey}
%
% \subsection{\hologo{LaTeX}-specific handlers}
%
@@ -3277,12 +3311,7 @@
% appends the reference key to the context. |\mmzNoRef| only does that if
% the reference is defined, otherwise it aborts the memoization.
\def\mmzForceNoRef#1{%
- \ifmemoizing
- \expandafter\gtoksapp\expandafter\mmzContextExtra
- \else
- \expandafter\toksapp\expandafter\mmzContext
- \fi
- {r@#1={\csname r@#1\endcsname}}%
+ \mmz@mtoc@csname{r@#1}%
\ignorespaces
}
\def\mmzNoRef#1{%
@@ -3360,11 +3389,17 @@
\endgroup
}
%</latex>
-%</mmz>
%
% \end{macro}
%
% \section{Support for various classes and packages}
+%
+%<*latex>
+\AddToHook{shipout/before}[memoize]{\global\advance\mmzExtraPages-1\relax}
+\AddToHook{shipout/after}[memoize]{\global\advance\mmzExtraPages1\relax}
+\mmzset{auto=\DiscardShipoutBox{
+ outer handler=\global\advance\mmzExtraPages1\relax\AdviceOriginal}}
+%</latex>
%
% \subsection{\TikZ;}
% \label{sec:code:mmz:tikz}
@@ -3373,7 +3408,6 @@
% Advice). All the action happens at the end of the preamble, so that we can
% detect whether \TikZ; was loaded (regardless of whether Memoize was loaded
% before \TikZ;, or vice versa), but still input the definitions.
-%<*mmz>
\mmzset{
begindocument/before/.append code={%
%<latex>\@ifpackageloaded{tikz}{%
@@ -3384,32 +3418,23 @@
% We define and activate the automemoization handlers for the \TikZ; command
% and environment.
\mmzset{%
- % \begin{listingregion}{_auto-tikz-collector.tex}
- auto=\tikz{memoize, collector=\AdviceCollectTikZArguments},
- % \end{listingregion}
- %/utils/exec={\tracingall},
- auto={tikzpicture}{memoize},
- % A hack to prevent memoizing pictures which are accidentally marked as
- % remembered --- accidentally in the sense that because the document
- % changed, the |.aux| file contains a |\pgfsyspdfmark| command which
- % erroneously refers to the picture being memoized. We know that
- % memoizing a remembered picture can't be right, as we always abort on
- % |\pdfsavepos|. This is implemented by hacking into PGF's
- % |\pgfsys@getposition|, and aborting memoization if the mark does not
- % equal |\relax|. (We have to duplicate |#| because of |.append code|.)
- auto=\pgfsys@getposition{
- run if memoizing, outer handler=\mmz@pgfsys@getposition},
- }%
- \def\mmz@pgfsys@getposition##1{%
- \expandafter\ifx\csname pgf@sys@pdf@mark@pos@##1\endcsname\relax
- \else
- \mmzAbort
- \fi
- \AdviceOriginal{##1}%
+ auto/memoize tikz/.style={
+ memoize,
+ at begin memoization=\edef\mmz@pgfpictureid{%
+ \the\pgf@picture@serial@count
+ },
+ at end memoization=\xtoksapp\mmzCCMemo{%
+ \unexpanded{%
+ \global\expandafter\advance\csname pgf@picture@serial@count\endcsname
+ }%
+ \the\numexpr\pgf@picture@serial@count-\mmz@pgfpictureid\relax\relax
+ },
+ },
+ auto=\tikz{memoize tikz, collector=\AdviceCollectTikZArguments},
+ auto={tikzpicture}{memoize tikz},
}%
},
}
-%</mmz>
%
%
% \subsection{Forest}
@@ -3417,7 +3442,6 @@
%
% Forest will soon feature extensive memoization support, but for now, let's
% just enable the basic, single extern externalization.
-%<*mmz>
%<*latex>
\mmzset{
begindocument/before/.append code={%
@@ -3478,6 +3502,98 @@
}{}}
%</latex>
%
+% \subsection{Morewrites}
+% \label{sec:code:morewrites}
+%
+% Use the old grammar for |\openin| and |\openout| as a temporary workaround.
+% |prefix|es containing spaces must be quoted manually.
+%<*latex>
+\AddToHook{begindocument/before}{%
+ \@ifpackageloaded{morewrites}{%
+ \def\mmz@openin#1#2{\openin#1=#2\relax}%
+ \def\mmz@openout#1#2{\openout#1=#2\relax}%
+ }{}%
+}
+%</latex>
+%
+% \subsection{Biblatex}
+% \label{sec:biblatex}
+%
+%<*latex>
+\mmzset{
+ begindocument/before/.append style={%
+ auto=\blx@bbl@entry{outer handler=\mmz@biblatex@entry},
+ auto/cite/.style={run if memoizing, outer handler=\mmz@biblatex@cite},
+ auto/cites/.style={run if memoizing, outer handler=\mmz@biblatex@cites},
+ auto=\cite{cite},
+ auto=\cites{cites},
+ }%
+}
+% \begin{macro}{\mmz@biblatex@entry}
+% This macro stores the MD5 sum of the |\entry| when reading the |.bbl| file.
+\def\mmz@biblatex@entry#1#2\endentry{%
+ \csxdef{mmz@bbl@#1}{\pdf@mdfivesum{#2}}%
+ \AdviceOriginal{#1}#2\endentry
+}
+% \end{macro}
+% \begin{macro}{\mmz@biblatex@cite}
+% This macro puts the cites reference keys into the context, and adds the
+% handled |\cite| command to the cc-memo.
+\def\mmz@biblatex@cite#1#{\mmz@biblatex@cite@i{#1}}
+\def\mmz@biblatex@cite@i#1#2{%
+ \forcsvlist\mmz@biblatex@cite@do@key{#2}%
+ \xtoksapp\mmzCCMemo{%
+ \noexpand\setbox0\noexpand\hbox{%
+ \expandonce\AdviceOriginal\unexpanded{#1}{#2}%
+ }}%
+ \AdviceOriginal#1{#2}%
+}
+\def\mmz@biblatex@cite@do@key#1{%
+ \mmz@mtoc@csname{mmz@bbl@#1}%
+ \ifcsdef{mmz@bbl@#1}{}{\mmzAbort}%
+}
+% \end{macro}
+% \begin{macro}{\mmz@biblatex@cites}
+% This macro puts the cites reference keys into the context, and adds the
+% handled |\cites| command to the cc-memo.
+\def\mmz@biblatex@cites{%
+ \mmz@temptoks{}%
+ \mmz@biblatex@cites@i
+}
+\def\mmz@biblatex@cites@i{%
+ \futurelet\mmz@temp\mmz@biblatex@cites@ii
+}
+\def\mmz@biblatex@cites@ii{%
+ \mmz@tempfalse
+ \ifx\mmz@temp\bgroup
+ \mmz@temptrue
+ \else
+ \ifx\mmz@temp[%]
+ \mmz@temptrue
+ \fi
+ \fi
+ \ifmmz@temp
+ \expandafter\mmz@biblatex@cites@iii
+ \else
+ \expandafter\mmz@biblatex@cites@z
+ \fi
+}
+\def\mmz@biblatex@cites@iii#1#{\mmz@biblatex@cites@iv{#1}}
+\def\mmz@biblatex@cites@iv#1#2{%
+ \forcsvlist\mmz@biblatex@cite@do@key{#2}%
+ \toksapp\mmz@temptoks{#1{#2}}%
+ \mmz@biblatex@cites@i
+}
+\def\mmz@biblatex@cites@z{%
+ \xtoksapp\mmzCCMemo{%
+ \noexpand\setbox0\noexpand\hbox{%
+ \expandonce\AdviceOriginal\the\mmz@temptoks
+ }}%
+ \expandafter\AdviceOriginal\the\mmz@temptoks
+}
+%</latex>
+% \end{macro}
+%
%
% \section{Initialization}
% \label{sec:code:initialization}
@@ -3512,6 +3628,10 @@
%</plain,context>
% \end{key}
%
+% Formats other than \hologo{plainTeX} need a way to prevent extraction during
+% package-loading.
+%<!plain>\mmzset{extract/no/.code={}}
+%
% \paragraph{\texttt{memoize.cfg}} Load the configuration file. Note that
% |nomemoize| must input this file as well, because any special
% memoization-related macros defined by the user should be available; for
@@ -3521,63 +3641,91 @@
%<mmz,nommz>\InputIfFileExists{memoize.cfg}{}{}
%<*mmz>
%
-% Formats other than \hologo{plainTeX} need a way to prevent extraction during
-% package-loading.
-\mmzset{
- %<!plain>extract/no/.code={},
-% \begin{key}{output directory}
-% \begin{macro}{mmzOutputDirectory}
-% Set the |-output-directory| --- manually, as there is no other way.
-% \indentmacrocode
- output-directory/.store in=\mmzOutputDirectory,
-}
-% \end{macro}
-% \end{key}
+% For formats other than \hologo{plainTeX}, we also save the current (initial
+% or |memoize.cfg|-set) value of |extract|, so that we can restore it when
+% package options include |extract=no|. Then, |extract| can be called without
+% an argument in the preamble, triggering extraction using this method; this is
+% useful e.g.\ if Memoize is compiled into a format.
+%<!plain>\let\mmz@initial@extraction@method\mmz@extraction@method
%
% \paragraph{Process} the package options (except in \hologo{plainTeX}).
-%<latex>\ProcessPgfPackageOptions{/mmz}
+%<*latex>
+\DeclareUnknownKeyHandler[mmz]{%
+ \expanded{\noexpand\pgfqkeys{/mmz}{#1\IfBlankF{#2}{={#2}}}}}
+\ProcessKeyOptions[mmz]
+%</latex>
%<context>\expandafter\mmzset\expandafter{\currentmoduleparameters}
-%
-% Define |\mmzOutputDirectory| if |output-directory| was not given.
-\ifdefined\mmzOutputDirectory
-\else
- \def\mmzOutputDirectory{}%
-\fi
-\mmzset{output directory/.code={\PackageError{memoize}{Key "output-directory"
- may only be used as a package option}{}}}
+%
+% In \hologo{LaTeX}, |nomemoize| has to process package options as well,
+% otherwise \hologo{LaTeX} will complain.
+%</mmz>
+%<*latex&nommz>
+\DeclareUnknownKeyHandler[mmz]{}
+\ProcessKeyOptions[mmz]
+%</latex&nommz>
+% \paragraph{Extern extraction}
+% We redefine |extract| to immediately trigger extraction. This is crucial in
+% \hologo{plainTeX}, where extraction must be invoked after loading the
+% package, but also potentially useful in other formats when package options
+% include |extract=no|.
+%<*mmz>
\mmzset{
- % \paragraph{Extract} the externs using the method given by |memoize.cfg| or
- % the package options --- unless we're running \hologo{plainTeX}.
- %<*!plain>
- extract/\mmz@extraction@method,
- % In non-\hologo{plainTeX} formats, also disable |extract| in the preamble.
- extract/.code={\PackageError{memoize}{Key "extract" is only allowed as a
- package option.}{If you really want to extract in the preamble, execute
- "extract/<method>".}},
- %</!plain>
- %<*plain>
- % In \hologo{plainTeX}, where extraction must be invoked after
- % loading the package, we now have to redefine |extract|, so that it will
- % immediately trigger extraction.
extract/.is choice,
extract/.default=\mmz@extraction@method,
% But only once:
extract/.append style={
- extract/.code={\PackageError{memoize}{Key "extract" is only allowed to
- be used once.}{If you really want to extract again, execute
- "extract/<method>".}},
+ extract/.code={\PackageError{memoize}{Key "extract" was invoked twice.}{In
+ principle, externs should be extracted only once. If you really want
+ to extract again, execute "extract/<method>".}},
},
- %</plain>
-}
+ % In formats other than \hologo{plainTeX}, we remember the current |extract|
+ % code and then trigger the extraction.
+ %<!plain>/utils/exec={\pgfkeysgetvalue{/mmz/extract/.@cmd}\mmz@temp@extract},
+ %<!plain>extract=\mmz@extraction@method,
+}
+% Option |extract=no| (which only exists in formats other than
+% \hologo{plainTeX}) should allow for an explicit invocation of |extract| in
+% the preamble.
+%<*!plain>
+\def\mmz@temp{no}
+\ifx\mmz@extraction@method\mmz@temp
+ \pgfkeyslet{/mmz/extract/.@cmd}\mmz@temp@extract
+ \let\mmz@extraction@method\mmz@initial@extraction@method
+\fi
+\let\mmz@temp@extract\relax
+%</!plain>
%
% Memoize was not really born for the draft mode, as it cannot produce new
-% externs there. But we don't want to disable the package, as utilization is
-% still perfectly valid in this mode, so let's just warn the user.
+% externs there. But we don't want to disable the package, as utilization and
+% pure memoization are still perfectly valid in this mode, so let's just warn
+% the user.
\ifnum\pdf@draftmode=1
- \PackageWarning{memoize}{No memoization will be performed in the draft mode}%
+ \PackageWarning{memoize}{No externalization will be performed in the draft mode}%
\fi
%</mmz>
%
+% Several further things which need to be defined as dummies in
+% |nomemoize|\slash|memoizable|.
+%<*nommz,mmzable&generic>
+\pgfkeys{%
+ /handlers/.meaning to context/.code={},
+ /handlers/.value to context/.code={},
+}
+\let\mmzAbort\relax
+\let\mmzUnmemoizable\relax
+\newcommand\IfMemoizing[2][]{\@secondoftwo}
+\let\mmzNoRef\@gobble
+\let\mmzForceNoRef\@gobble
+\newtoks\mmzContext
+\newtoks\mmzContextExtra
+\newtoks\mmzCMemo
+\newtoks\mmzCCMemo
+\newcount\mmzExternPages
+\newcount\mmzExtraPages
+\let\mmzTracingOn\relax
+\let\mmzTracingOff\relax
+%</nommz,mmzable&generic>
+%
% \paragraph{The end} of |memoize|, |nomemoize| and |memoizable|.
%<*mmz,nommz,mmzable>
%<plain>\resetatcatcode