# LaTeX3 Create environment around token list variable

LaTeX3 has some great concepts and functions. One is the ability to replace text in a token list. This opens up possibilities to create templates in a way that html templates are used for example by handlebars

The only reason for the existence of such templates is to simplify the entering of mark-up, being either by humans or computers. Consider the case of having mark-up for multiple images such as the one below:

The mark-up can get very tedious. A markup of the form:

!!img amato!!
!!cap This is the first caption!!


would greatly simplify the mark-up. The !!img is a marker to pick-up images and !!cap to pickup captions. I have used the !! as a marker but of course anything can be used as long as is allowed by a token list. The three letters that follow denote different mark-up, i.e. img for image, cap for caption.

Here is the code:

\documentclass{article}
\usepackage{expl3, graphicx,caption}
\begin{document}

\ExplSyntaxOn
\cs_set:Npn  \putimage#1!!{%
\includegraphics[width=\linewidth]{./images/amato}%
}

\cs_set:Npn  \putsomecaption#1!!{
\captionof{figure}{#1}
\par\endminipage\hfill
}

\tl_set:Nn \tempai {
\centering
!!img amato!!
!!cap This~is~the~first~caption!!

!!img amato!!
!!cap This~is~the~second~caption!!

!!img amato.jpg!!
!!cap This~is~the~third~caption!!

!!img amato!!
!!cap This~is~the~fourth~caption!!

!!img amato!!
!!cap This~is~the~fifth~caption!!

!!img amato!!
!!cap This~is~the~sixth~caption!!
}

\tl_replace_all:Nnn\tempai {!!img}{\minipage{3.6cm}\centering\putimage}
\tl_replace_all:Nnn\tempai {!!cap}{\putsomecaption}
\tl_use:N \tempai
\ExplSyntaxOff
\end{document}


I have difficulties turning the above code in a suitable environment. Can someone provide a solution. Say to have an environment multimages.

• May be a double map? (It's in the documentation interface3.pdf I think) like \foo{ {amato}{The ~ caption} {amato}{Another ~ caption} .. } and let expl3 handle all? May 14, 2015 at 18:58
• @Manuel Thanks. user input must be as I have shown it. Problem is to define a suitable environment. \begin{multimages}...\end{multimages} to hold the user input. May 14, 2015 at 19:02
• you presumably don't want user input to be in the scope of the l3 programming conventions where space has to be entered as ~ ? That was never intended for entering any kind of user text, although can be used for small fixed texts such as error messages within the program code of course. May 14, 2015 at 19:05
• environ package allows to create a token list from an environment “\BODY”, there, you replace {!!img} and {!!cap} and I think you are done. To be more “free”, you could take a look at l3regex. May 14, 2015 at 19:06
• @DavidCarlisle Sure that is why I am looking at a suitable environment. May 14, 2015 at 19:13

I don't think this is simpler input. However, pursuing further Manuel's idea, here's a version with full featured options.

\documentclass{article}
\usepackage{showframe}
\usepackage{xparse,mwe,graphicx,caption,environ}

\ExplSyntaxOn
\NewEnviron{multiimages}[1][]
{
\keys_set:nn { yl/multiimages } { #1 }
\tl_use:N \l_yl_multi_start_tl
\dim_set:Nn \parindent { 0pt }
\skip_set:Nn \leftskip { 0pt plus 1fil }
\skip_set:Nn \rightskip { 0pt plus -1fil }
\skip_set:Nn \lineskip { \l_yl_multi_skip_skip }
\yl_multiimages:V \BODY
\tl_use:N \l_yl_multi_end_tl
}

\tl_new:N \l_yl_multi_start_tl
\tl_new:N \l_yl_multi_end_tl

\keys_define:nn { yl/multiimages }
{
env .choice:,
env/none .code:n =
\tl_set:Nn \l_yl_multi_start_tl { \par\addvspace{\topsep} }
\tl_set:Nn \l_yl_multi_end_tl { \par\addvspace{\topsep} },
env/figure .code:n =
\tl_set:Nn \l_yl_multi_start_tl { \__yl_multi_beginfigure:V \l_yl_multi_pos_tl }
\tl_set:Nn \l_yl_multi_end_tl { \end{figure} },
env .initial:n = none,

pos .tl_set:N = \l_yl_multi_pos_tl,
pos .initial:n = { htp },

outer .dim_set:N = \l_yl_multi_outer_dim,
outer .initial:n = 3.6cm,
inner .dim_set:N = \l_yl_multi_inner_dim,
inner .initial:n = 3.6cm,

skip .dim_set:N = \l_yl_multi_skip_skip,
skip .initial:n = \lineskip,

last .choice:,
last/fill .code:n =
\tl_set:Nn \l_yl_multi_last_tl { { \parfillskip=0pt\par } },
last/center .code:n =
\tl_set:Nn \l_yl_multi_last_tl { { \parfillskip=0pt plus 2fil\par } },
last .initial:n = fill,
}

\cs_new_protected:Npn \__yl_multi_beginfigure:n #1
{
\begin{figure}[#1]
}
\cs_generate_variant:Nn \__yl_multi_beginfigure:n { V }

\cs_new_protected:Npn \yl_multiimages:n #1
{
\tl_set:Nn \l_tmpa_tl { #1 }
\tl_remove_all:Nn \l_tmpa_tl { \par }
\tl_replace_all:Nnn \l_tmpa_tl { !!img ~ } { \__yl_multi_img:w }
\tl_replace_all:Nnn \l_tmpa_tl { !!cap ~ } { \__yl_multi_cap:w }
\tl_use:N \l_tmpa_tl \tl_use:N \l_yl_multi_last_tl
}
\cs_generate_variant:Nn \yl_multiimages:n { V }

\cs_new_protected:Npn \__yl_multi_img:w #1 !!
{
\begin{minipage}{\l_yl_multi_outer_dim}\centering
\includegraphics[width=\l_yl_multi_inner_dim]{ #1 }
}
\cs_new_protected:Npn \__yl_multi_cap:w #1 !!
{
\captionof{figure}{#1}
\end{minipage}\hspace{1pc plus 3pc}
}
\ExplSyntaxOff

\begin{document}

\begin{multiimages}[env=figure,pos=ht]
!!img example-image-a!!
!!cap This is the first caption!!

!!img example-image-a!!
!!cap This is the second caption!!

!!img example-image-a!!
!!cap This is the third caption!!

!!img example-image-a!!
!!cap This is the fourth caption!!

!!img example-image-a!!
!!cap This is the fifth caption!!

!!img example-image-a!!
!!cap This is the sixth caption!!
\end{multiimages}

\begin{multiimages}[last=center]
!!img example-image-a!!
!!cap This is the first caption!!

!!img example-image-a!!
!!cap This is the second caption!!

!!img example-image-a!!
!!cap This is the third caption!!

!!img example-image-a!!
!!cap This is the fourth caption!!

!!img example-image-a!!
!!cap This is the fifth caption!!

\end{multiimages}

\begin{multiimages}[last=center,env=figure,pos=p,inner=3cm,skip=10ex]
!!img example-image-a!!
!!cap This is the first caption!!

!!img example-image-a!!
!!cap This is the second caption!!

!!img example-image-a!!
!!cap This is the third caption!!

!!img example-image-a!!
!!cap This is the fourth caption!!

!!img example-image-a!!
!!cap This is the fifth caption!!

\end{multiimages}

\end{document}


• Thanks. Is there no way to collect the BODY other than using the environ package? It is kind of sad that environ uses toks and the idea behind the expl3 token lists was to avoid and improve them by recreating them with tl. May 15, 2015 at 1:55
• Should it be \begin{figure}[\l_yl_multi_pos] or \begin{figure}[\l_yl_multi_pos_tl]? May 15, 2015 at 4:00
• @YiannisLazarides Yes, but it should be done in a less direct way. Fixed. May 15, 2015 at 9:17
\documentclass{article}
\usepackage{xparse,mwe,graphicx,caption,environ}

\NewEnviron{multiimages}{\processmultiimages{\BODY}}

\ExplSyntaxOn
\NewDocumentCommand \processmultiimages { m }
{ \par \centering \yl_multiimages:N #1 }
\cs_new_protected:Npn \yl_multiimages:N #1
{
\tl_set_eq:NN \l_tmpa_tl #1
\tl_remove_all:Nn \l_tmpa_tl { \par }
\tl_replace_all:Nnn \l_tmpa_tl { !!img ~ }
{ \begin{minipage}{3.6cm}\centering\multiimg }
\tl_replace_all:Nnn \l_tmpa_tl { !!cap ~ }
{ \multiimgcapt }
\tl_use:N \l_tmpa_tl
}
\NewDocumentCommand \multiimg { u{!!} }
{ \includegraphics[width=\linewidth]{ #1 } }

\NewDocumentCommand \multiimgcapt { u{!!} }
{ \captionof{figure}{#1} \par\end{minipage}\hfill }
\ExplSyntaxOff

\begin{document}

\begin{multiimages}
!!img example-image-a!!
!!cap This is the first caption!!

!!img example-image-a!!
!!cap This is the second caption!!

!!img example-image-a!!
!!cap This is the third caption!!

!!img example-image-a!!
!!cap This is the fourth caption!!

!!img example-image-a!!
!!cap This is the fifth caption!!

!!img example-image-a!!
!!cap This is the sixth caption!!
\end{multiimages}

\end{document}


I don't see the real point of this though. And I think you should take a look at l3regex's regular expressions.

• Thanks. I had a look at Bruno's l3regex sometime back. At the time I thought that if one needs such complexity it was better tto use Lua and lpeg. The point of my request is to simplify user input. May 14, 2015 at 19:35
• You already had it (I just added the environ). In any case, the thing about l3regex is that you replace at once everything like \regex_replace_all:nnN { \!\!img\ (.+?)\!\! } { \c{whatevercommand} \cB\{\1\cE\} } \l_tmpa_tl (sorry if there's a mistake, this is from memory, I'm not an expert either) and you don't have “weird delimited arguments”. May 14, 2015 at 19:38
• May be you have the opportunity to have a full-featured-keys-included-solution from egreg :) May 14, 2015 at 19:46

To be honest an input syntax like !!img zzz!! seems more complicated than a simple tex syntax such as \img{zzz} but anyway expl3 is of course useful for lots of things but it seems inefficient to grab the environment body and then do token replacements in a second pass and then finally execute the modified list in the third pass, you could simply typeset it in one pass, something like

\documentclass{article}
\usepackage{graphicx,capt-of}

\def\multiimages{\centering\zzz}
\def\endmultiimages{\par}

\long\def\zz#1!img #2!!#3!!cap #4!!{%
\begin{minipage}{3.6cm}\centering
\includegraphics[width=\linewidth]{#2}%
\captionof{figure}{#4}%
\end{minipage}\hfill\zzz}

\def\zzs{!}
\def\zzp{\par}

\long\def\zzz#1{%
\def\tmp{#1}%
\ifx\tmp\zzs\expandafter\zz
\else
\ifx\tmp\zzp\expandafter\expandafter\expandafter\zzz
\else
\expandafter\expandafter\expandafter\end
\fi
\fi}

\begin{document}

\begin{multiimages}
!!img example-image-b!!
!!cap This is the first caption!!

!!img example-image-b!!
!!cap This is the second caption!!

!!img example-image-b!!
!!cap This is the third caption!!

!!img example-image-b!!
!!cap This is the fourth caption!!

!!img example-image-b!!
!!cap This is the fifth caption!!

!!img example-image-b!!
!!cap This is the sixth caption!!
\end{multiimages}

\end{document}

• Thanks for the compliment regarding the more complicated part, I must be now truly getting into the spirit of expl3! One of course could delimit with one !. May 14, 2015 at 20:39

My example don't use expl3, but simply \replacestring from OPmac.

\input opmac

\long\def\putimages#1{\def\tmpb{#1}%
\replacestrings{!!img }{\img}%
\replacestrings{!!cap }{\cap}%
\replacestrings{.jpg!!}{!!}%
\tmpnum=0
\hbox to\hsize{\tmpb}% three imeges per line
}
\def\img#1!!#2\cap#3!!{%
\ifnum\tmpnum=3 \egroup\bigskip\hbox to\hsize\bgroup \tmpnum=0 \fi
\vbox{\hsize=.3\hsize
\centerline{\picw=4cm \inspic #1.jpg }
\caption/f \emergencystretch=2em #3\par
}\hss
}
\def\thefnum{\the\fnum}

\putimages{
!!img amato!!
!!cap This is the first caption!!

!!img amato!!
!!cap This is the second caption!!

!!img amato.jpg!!
!!cap This is the third caption!!

!!img amato!!
!!cap This is the fourth caption!!

!!img amato!!
!!cap This is the fifth caption!!

!!img amato!!
!!cap This is the sixth caption!!
}
\bye


The result is the same as in your 3x2 picture.

Explanation: The first pass converts the data to:

\img amato!! \cap This is the first caption!! \par\img amato!! \cap ...


This is stored in \tmpb. Then \hbox{\tmpb} creates 3x2 picture matrix because \ifnum\tmpnum=3 then \hbox is closed and new \hbox is opened.