Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I would like to create new command with functionality like this (pseudo code):

\newcommand{\myCommand}[numOfParameters]  { 
  for (i = 0; i < numOfParameters / 3; i++) {
     \somecommand1{#(i*3 + 1)}
     \somecommand1{#(i*3 + 2)}
     \somecommand1{#(i*3 + 3)}
  }
}

Is it possible to implement such like this in LaTeX ?

Here is example of usage (by request):

Here is a macros to show 2 images per row ...

\newcommand{\twoimages}[6] {
    \begin{figure}[htb!]
        \begin{minipage}[h]{0.49\linewidth}
            \begin{center}
                \includegraphics[width=#3\linewidth]{#1} \\ 
                \caption{#2} 
                \label{ris:#1}
            \end{center}
        \end{minipage}
        \hfill
        \begin{minipage}[h]{0.49\linewidth}
            \begin{center}
                \includegraphics[width=#6\linewidth]{#4} \\ 
                \caption{#5}
                \label{ris:#4}
            \end{center}
        \end{minipage}
    \end{figure}
}

I'd like to make macros for N (user-defined number) images

share|improve this question
    
A command with a variable number of arguments is not possible as-is. LaTeX usually employs comma-separated lists for this kind of thing. See “For loop” in newcommand. But you also can make a command with one argument which gets an arbitrarily long list of macro calls like this: \images{\image{foo}{bar}{.4}\image{baz}{quux}{.5}...}. –  Stephan Lehmke Sep 17 '12 at 14:38

2 Answers 2

up vote 13 down vote accepted

You can define recursive macros that call themselves until some termination is found; a solution to your problem can be as follows:

\makeatletter % we need to use kernel commands
\newcommand{\twoimages}{%
  \begin{figure}[!htb]
  \@twoimagesi
}
\newcommand\@twoimagesi{\@ifnextchar\stopimages{\@twoimagesend}{\@twoimagesii}}

\newcommand\@twoimagesii[6]{%
  \@twoimagesiii{#1}{#2}{#3}\hfill
  \@twoimagesiii{#4}{#5}{#6}\\[\bigskipamount]
  \@twoimagesi % restart the recursion
}
\newcommand\@twoimagesiii[3]{%
  \begin{minipage}{0.49\linewidth}
    \centering
    \includegraphics[width=#3\linewidth]{#1}
    \caption{#2}\label{ris:#1}
  \end{minipage}}
\newcommand\@twoimagesend[1]{% The argument is \stopimages
  \vspace*{-\bigskipamount}
  \end{figure}}
\makeatother

The macro \twoimages really has no argument; it simply starts the business by opening the figure environment and calls the real command, \@twoimagesi. This command checks whether it's followed by \stopimages; if it is, it calls \@twoimagesend that ends the environment; otherwise it executes \@twoimagesii that has the job of printing a row, after having absorbed its six arguments. It does so in an indirect way, so that we can write only once the same minipage, using the first three arguments and the last three.

Then \@twoimagesii restarts the recursion by calling \@twoimagesi again.


Let's see a complete example (I use the demo option to graphicx that draws a black blob instead of requiring external files).

\documentclass{article}
\usepackage[demo]{graphicx}

\makeatletter % we need to use kernel commands
\newcommand{\twoimages}{%
  \begin{figure}[!htb]
  \@twoimagesi
}
\newcommand\@twoimagesi{\@ifnextchar\stopimages{\@twoimagesend}{\@twoimagesii}}

\newcommand\@twoimagesii[6]{%
  \@twoimagesiii{#1}{#2}{#3}\hfill
  \@twoimagesiii{#4}{#5}{#6}\\[\bigskipamount]
  \@twoimagesi % restart the recursion
}
\newcommand\@twoimagesiii[3]{%
  \begin{minipage}{0.49\linewidth}
    \centering
    \includegraphics[width=#3\linewidth]{#1}
    \caption{#2}\label{ris:#1}
  \end{minipage}}
\newcommand\@twoimagesend[1]{% The argument is \stopimages
  \vspace*{-\bigskipamount}
  \end{figure}}
\makeatother

\begin{document}
\twoimages
  {a}{Caption left}{.5}
  {b}{Caption right}{.5}
  {c}{Caption left}{.5}
  {d}{Caption right}{.5}
\stopimages
\end{document}

enter image description here


A quite different approach is via the expl3 macros. Also the syntax will be different; I'll present the example, which is almost self-explanatory: the main macro splits its argument at the commas and each chunk is processed in a very similar way as before.

\documentclass{article}
\usepackage[demo]{graphicx}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\twoimages}{ >{ \SplitList {,} } m }
 {
  \begin{figure}[!htb]
  \centering
  \ProcessList { #1 } { \davs__twoimages_row:n }
  \vspace{-\bigskipamount}
  \end{figure}
 }
\cs_new_protected:Nn \davs__twoimages_row:n
 {
  \davs__twoimages_row:nnnnnn #1
 }
\cs_new_protected:Nn \davs__twoimages_row:nnnnnn
 {
  \davs__twoimages_do:nnn { #1 } { #2 } { #3 } 
  \hfill
  \davs__twoimages_do:nnn { #4 } { #5 } { #6 }
  \\[\bigskipamount]
 }
\cs_new_protected:Nn \davs__twoimages_do:nnn
 {
  \begin{minipage}{0.49\linewidth}
    \centering
    \includegraphics[width=#3\linewidth]{#1}
    \caption{#2}\label{ris:#1}
  \end{minipage}
 }
\ExplSyntaxOff
\begin{document}

\twoimages{
  {a}{Caption left}{.5}
  {b}{Caption right}{.5},
  {c}{Caption left}{.5}
  {d}{Caption right}{.5}
}

\end{document}

The result is exactly the same as before. There can be any number of sixtuples of arguments, separated by a comma.


Just for completeness, a version that accepts any number of images; now each triple should be separated by a comma; if the number of images is odd, the last one will be centered.

\documentclass{article}
\usepackage[demo]{graphicx}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\twoimages}{ >{ \SplitList {,} } m }
 {
  \begin{figure}[!htb]
  \centering
  \leftskip=\fill \rightskip=\fill
  \lineskip=\baselineskip % to compensate for the minipages
  \ProcessList { #1 } { \__davs_process_argument:n }
  \end{figure}
 }
\cs_new_protected:Nn \__davs_process_argument:n
 {
  \__davs_image:nnn #1
 }
\cs_new_protected:Nn \__davs_image:nnn
 {
  \hspace*{\fill}
  \begin{minipage}{0.49\linewidth}
    \centering
    \includegraphics[width=#3\linewidth]{#1}
    \caption{#2}\label{ris:#1}
  \end{minipage}
  \hspace*{\fill}
  \penalty0 % we provide a break point
 }
\ExplSyntaxOff
\begin{document}

\twoimages{
  {a}{Caption left}{.5},
  {b}{Caption right}{.5},
  {c}{Caption left}{.5},
  {d}{Caption right}{.5},
  {e}{Caption center}{.5}
}

\end{document}
share|improve this answer

The following example uses the syntax that the arguments are given inside the argument for the command: \images{{...}{...}{...}{...}{...}{...}...}. The macro \images then parses its argument and catches three arguments at a time:

\documentclass{article}

\newif\ifimagesSep
\newcommand*{\images}[1]{%
  \par\noindent[begin images]\\\relax
  \imagesSepfalse
  \imagesScan#1\relax\relax\relax
  [end images]\par
}
\newcommand{\imagesScan}[3]{%
  \ifx\relax#1\empty
  \else
    \ifimagesSep
      [separation]\\\relax
    \else
      \imagesSeptrue
    \fi
    [image: #1 #2 #3]\\\relax
    \expandafter\imagesScan
  \fi
}

\begin{document}

\images{
  {w1}{l1}{c1}
  {w2}{l2}{c2}
  {w3}{l3}{c3}
}
\end{document}

Result

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.