sasozivanovic / memoize

A cross-format package for externalization of graphics and memoization of compilation results in general
LaTeX Project Public License v1.3c
16 stars 3 forks source link

meaning-to-context with NewDocumentCommand/NewDocumentEnvironment #20

Closed atticus-sullivan closed 4 months ago

atticus-sullivan commented 4 months ago

Hi,

after I've recently found this package (via the announcements in TUGboat before the current one), I've been playing around with it a bit. I've read the docs (maybe not section 4) so I hope that I'm not missing something and this question is not already answered there.

The thing I'm trying to is quite similar to the one on page 14 (2.4) in the docs but with \NewDocumentCommand instead of using (the "old") \newcommand. (Ok to be more precise in the end I'd need a \NewDocumentEnvironment but until now I tried to stay close to the example.)

So my minimal (not) working example would be something like

\documentclass{article}

\usepackage{memoize}
\usepackage{tikz}

\NewDocumentCommand\answer{}{4}

\begin{document}

\mmznext{meaning to context=\answer}
\tikzset{
    emph/.style={fill=yellow, text=blue},
    emph/.meaning to context,
}
\begin{tikzpicture}
    \node[emph]{The answer is \answer!};
\end{tikzpicture}

\end{document}

changing \answer to 42 does not trigger an update of the memoized "picture".

Am I missing something here, or does meaning to context only work with \newcommand and \newenvironment?

Oh and in case it matters:

Version information ```bash $ pdflatex --version pdfTeX 3.141592653-2.6-1.40.26 (TeX Live 2024) $ tlmgr info memoize package: memoize category: Package shortdesc: Externalization of graphics and memoization of compilation results in general longdesc: Memoize is a package for externalization of graphics and memoization of compilation results in general, allowing the author to reuse the results of compilation-intensive code. Memoize (i) induces very little overhead, as all externalized graphics is produced in a single compilation. It features (ii) automatic recompilation upon the change of code or user-adjustable context, and (iii) automatic externalization of TikZ pictures and Forest trees, easily extensible to other commands and environments. Furthermore, Memoize (iv) supports cross-referencing, TikZ overlays and Beamer, (v) works with all major engines and formats, and (vi) is adaptable to any workflow. installed: Yes revision: 70841 sizes: src: 161k, doc: 3657k, run: 249k, bin: 17k relocatable: No cat-version: 1.3.0 cat-license: lppl1.3c cat-topics: compilation ext-code cond-comp macro-gen graphics cat-contact-repository: https://github.com/sasozivanovic/memoize collection: collection-pictures ```

should be fairly up-to-date.


Btw I really appreciate your work. I've been working myself on a modified version/wrapper of the tikzexternal library (mostly to avoid the recompile if e.g. only the ordering changed), but putting each extern on a single page and thereby generating all externs on one compile process is pretty nice and also the ability to freely configure what should be memoized is far beyond what I've written (or moreover drafted).

sasozivanovic commented 4 months ago

Hi!

I'm glad you find the package useful!

For commands defined with \NewDocumentCommand and friends, you should use the following variant of meaning to context: csname meaning to context=<command name> code. So, in the case above, csname meaning to context=answer code.

This is because a macro defined by \NewDocumentCommand only contains code which calls the LaTeX3 argument parser, and therefore does not change unless you change the argument structure of the command. The "real" definition of the command is accessible by control sequence \<command name> code (note the space). You can see this (in the log) if you write \show\answer and \csshow{answer code}.

I haven't thought of this when I was writing the documentation (meaning to context was a late addition). I'll fix it in the next release.

atticus-sullivan commented 4 months ago

Oh nice that this is already possible. I've been trying csname meaning to context but I was missing the code in the end. Sorry to further bother you again but this does not seem to be working for \NewDocumentEnvironment for me:

\documentclass{article}

\usepackage{memoize}
\usepackage{tikz}

\NewDocumentCommand{\start}{}{x}

% \mmzset{auto={myEnv}{memoize}}
\NewDocumentEnvironment{myEnv}{}{
    beginX
}{
    end
}

\begin{document}

\mmznext{csname meaning to context=myEnv code}
\begin{tikzpicture}
\node[]{
    \begin{myEnv}
        my text
    \end{myEnv}
};
\end{tikzpicture}

\end{document}

(also you can see, the final goal is more to add the definition of the memoized environment to the context, for these tests I just stick to tikzpicture to avoid problems when using auto={}{memoize} together with meaning to context)

sasozivanovic commented 4 months ago

No problem, happy to help. The following works for me:

\mmznext{
  csname meaning to context=environment myEnv code,
  csname meaning to context={{environment myEnv end aux }}, % note the space after "aux"! This is why double braces are needed.
  % csname meaning to context=environment myEnv end aux\space, % alternative
  % csname meaning to context={environment myEnv end aux }, % this does not work
}

However, I figured this out by looking at the LaTeX(3) source, which I don't fully comprehend, and I cannot guarantee that it will work in general, especially wrt changes in the end-of-environment code. If/when it doesn't, I suggest you post a question to TeX.SE, asking where LaTeX3 stores the begin/end environment code.

atticus-sullivan commented 4 months ago

Ok nice, works for me. Also my (simple) test indicates that this also works for changes in the end-of-env code. Also thanks for the fast replies.

Not sure if it generally makes sense, but maybe as an idea for the future it might be an idea to automatically add the definition of a memoized command/environment to its context.

sasozivanovic commented 4 months ago

Glad to hear this!

It is a nice idea, but I don't think it is possible to implement in general, as the definition of a command can be spread across many many macros. You can always create a style for simple commands you define yourself (so when you know how it is defined). For example, something like my auto/.style 2 args={auto=#1{#2}, meaning to context=#1} should work for a command defined by a single \newcommand.

cfr42 commented 4 months ago

I would not want the definition of forest or tikzpicture, say, added to the context of every forest or tikzpicture because I wouldn't want them all recompiled just because the package changed the definition. Nor would I want every prooftree or chronos environment to get recompiled if the definition changed. Or, rather, I might want that to happen, but I might very well not and it doesn't seem to me it's something memoize should do by default, even if it was possible. (But 'should' is tricky. Let's just say I'd really hope there was a way to switch it off!)