I am trying to learn how to do typesetting (delaying typesetting until later in the document), and am doing an example with recreating the figure. It is used like this:
\begin{myfigure}
\mycaption{Foo}
\end{myfigure}
I would simply like to take that \mycaption{Foo} and place it into the \caption at the proper place in the document.
The full MWE is here:
\documentclass[a4paper]{article}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{tikz}
\usepackage{xifthen}
\ExplSyntaxOn
\begin{document}
\NewDocumentEnvironment{myfigure}{mm} {
\tl_new:N \l_myfigure_mycaption_tl
\NewDocumentCommand{\mycaption}{m} {
\tl_set:Nn \l_myfigure_mycaption_tl {#1}
}
\begin{figure}
\begin{tikzpicture}
}{
\end{tikzpicture}
% a latex3 way of doing if-statement would be helpful to know.
\ifthenelse{\isempty{\l_myfigure_mycaption_tl}}
{}
{\caption{\l_myfigure_mycaption_tl}}
\end{figure}
}
\begin{myfigure}
\mycaption{Foo}
\end{myfigure}
\end{document}
In that, I try creating the API \mycaption like this:
\tl_new:N \l_myfigure_mycaption_tl
\NewDocumentCommand{\mycaption}{m} {
\tl_set:Nn \l_myfigure_mycaption_tl {#1}
}
I am trying to make this tl variable a local variable to the environment myfigure. I am trying to make it so it's not created globally outside of the environment, yet I want to use it in the "after block" of the environment.
Then I check if that variable is blank, and if it is not blank, I typeset the caption.
The goal is to be able to:
- Define an API variable (e.g.
\mycaption) to use for setting a value in an environment, and - Plugging that value into the appropriate place later in the document flow.
- Not sure if nesting the
\NewDocumentCommandis correct (as per the comments under this answer: How to define nested environments and commands in LaTeX3)
This is essentially a getter/setter approach, so I'm wondering if this is the correct approach or there is a better alternative. If there is a better alternative that would be good to know, otherwise just knowing how to accomplish it using the approach I have outlined is helpful as well.
The caption shows up blank in my MWE.

\l_....syntax the 'variables' aren't local. You have to use the\....set:...macros and\group_begin:and\group_end:to keep their values local, i.e. in a group.\tl_new:Nin a macro that is called repeatedly is bad, however, since it will complain at the 2nd usage – Mar 25 '18 at 20:44\NewDocumentCommandcalls then most likely something is wrong, that should almost always just be the declaration of the top level document syntax. – David Carlisle Mar 25 '18 at 20:51\NewDocumentCommand, but don't understand (a) why that works and (b) why that's wrong. Maybe related to https://tex.stackexchange.com/questions/422985/best-practices-on-when-to-create-a-new-function-vs-a-command-in-latex3 – Lance Mar 25 '18 at 20:52\tl_if_empty:NF \l_myfigure_my_caption {foo}is what you want for the\ifthenelse... test – Mar 25 '18 at 20:53\tl_set:Nninside of the doubled nestedfigure\tikzpicturewon't work to make the content of the\l_myfigure...tlvariable alive after\end{tikzpicture}, since\mycaptionis effectively called inside thetikzpictureenvironment. It is local, but then lost aftertikzpicture– Mar 25 '18 at 21:05myfigureenviornment to take two arguments\NewDocumentEnvironment{myfigure}{mm} {so in the use the first argument is\captionand the second argument isFoobut all three answers have already posted fixed versions of the declaration. – David Carlisle Mar 25 '18 at 21:28