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'm trying to define a new command \multiboxed in LaTeX so that I can put n boxes around an equation without having to manually nest \boxed commands. So far I have (using the pgffor package):

def\multiboxed#1#2{
  \foreach \index in {1, ..., #1} {
      Hello
  }
  #1
  \foreach \index in {1, ..., #1} {
    World
  }
}

which successfully wraps the second argument with Hello and World a number of times equal to the first argument. However, changing this to

def\multiboxed#1#2{
  \foreach \index in {1, ..., #1} {
      \fbox{
  }
  #1
  \foreach \index in {1, ..., #1} {
    }
  }
}

really doesn't work, as expected. As such, I have two questions which I only really need an answer to one of:

  1. How do I successfully modify the for loops to achieve the desired behaviour?
  2. Alternatively, how do I define a recursive command to achieve the same output?

Obviously an answer to (2) would be better as this is a better way of solving the problem, but I have a feeling I'd better understand an answer to (1). Ideally I'd also not have to rely on the pgffor package. Thanks for any light you can shed on this matter.

share|improve this question

5 Answers 5

up vote 11 down vote accepted

Nothing wrong with the the answers so far but they all use big heavyweight packages, this version doesn't use any package at all and needs rather less code.

enter image description here

\documentclass{article}

\def\Fbox#1#2{\ifnum#1=0\mbox{#2}\else\fbox{\Fbox{\numexpr#1-1\relax}{#2}}\fi}


\begin{document}

\Fbox{0}{hello}
\Fbox{1}{hello}
\Fbox{2}{hello} 
\Fbox{3}{hello} 
\Fbox{4}{hello} 
\Fbox{5}{hello} 

\end{document}

Another variant using \@first/@secondoftwo:

\makeatletter
\def\Fbox#1#2{%
  \ifnum#1=0\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\mbox{#2}}{\fbox{\Fbox{\numexpr#1-1\relax}{#2}}}%
}
\makeatother
share|improve this answer
    
Nice. I particularly like the lack of extra packages. –  rbobbington Nov 18 '12 at 1:50

A token register can collect the nested \fbox commands. \global is needed, because the body of \foreach is executed in a group.

\documentclass{article}
\usepackage{pgffor}

\newtoks\ToksMultiBoxed
\newcommand*{\multiboxed}[2]{%
  \global\ToksMultiBoxed{#2}%
  \ifnum#1>0 %
    \foreach \index in {1,...,#1} {%
      \global\ToksMultiBoxed\expandafter{%
        \expandafter\fbox\expandafter{\the\ToksMultiBoxed}%
      }%
    }%
  \fi
  \the\ToksMultiBoxed
}

\begin{document}

\multiboxed{4}{Hello}
\multiboxed{1}{World}
\multiboxed{0}{!}

\end{document}

Result

\documentclass{article}
\usepackage{loops}[2012/10/16]
\makeatletter
\newcommand*{\multiboxed}[2]{%
  \skvifnumTF#1=\z@{%
    #2%
  }{%
    \@temptokena{#2}%
    \foreachfox {1,...,#1} {%
      \skvexpanded{\@temptokena{\noexpand\fbox{\the\@temptokena}}}%
    }%
    \the\@temptokena
  }%
}
\makeatother  
\begin{document}
\multiboxed{4}{Hello}
\multiboxed{1}{World}
\multiboxed{0}{!}
\end{document}
share|improve this answer
    
Thanks very much. I'm not going to pretend I understand everything that the code does, but I'll look into it... –  rbobbington Nov 18 '12 at 0:10

As David Carlisle says there is nothing wrong with the other answers. That is, as long as you are satisfied with just a plain box. But when it comes to drawing boxes, nothing beats the tikz way:

enter image description here

The extra spacing is achieved by using a white line for two of the boxes.

Code:

\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}

\tikzset{Dotted Red/.style={draw=red, dotted, line width=1pt}}
\tikzset{Dashed Violet/.style={draw=violet, dashed}}

\newcommand{\Boxed}[3][]{
\begin{tikzpicture}[baseline, inner sep=0, outer sep=0]
    \node [thick] (Origin) {#3};
    \foreach \x in {1,...,#2} {%
        \pgfmathsetmacro{\Shift}{0.1*(\x+1)}%
        \StrBetween[\x,\numexpr\x+1\relax]{,#1,}{,}{,}[\LineStyle]
        \draw [thick, draw=black, \LineStyle] 
            ([shift={(-\Shift cm,-\Shift cm)}]Origin.south west) rectangle 
            ([shift={( \Shift cm, \Shift cm)}]Origin.north east) ;
    }%
\end{tikzpicture}
}



\begin{document}
    \Boxed{3}{Hello}
    \hspace{1cm}
    \Boxed[blue,black,green,violet,red]{5}{Hello World}

    \bigskip
    \hspace{1.0cm}\Boxed[blue,black,white,white,Dashed Violet,Dotted Red]{6}{How you doin?}
\end{document}
share|improve this answer
1  
OMG COLORS!!!!! –  yo' Nov 18 '12 at 9:06

The opening and closing braces of the argument to \fbox need to be in the same scope. Here's a possible solution:

\documentclass{article}

\usepackage{pgffor}

\newtoks\boxcontenttok

\def\multiboxed#1#2{%
  \boxcontenttok{#2}%
  \foreach \index in {1, ..., #1} {%
    \edef\boxcontent{\noexpand\fbox{\the\boxcontenttok}}%
    \expandafter\global\expandafter\boxcontenttok\expandafter{\boxcontent}%
  }%
  \the\boxcontenttok
}

\begin{document}

\multiboxed{3}{Hello World}

\end{document}
share|improve this answer
    
Thanks very much. I'm not going to pretend I understand everything that the code does, but I'll look into it... –  rbobbington Nov 18 '12 at 0:11

Here's an implementation with xparse and expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\multibox}{mm}
 {
  \multibox_do:nn { #1 } { #2 }
 }

\tl_new:N \l_multibox_tokens_tl
\cs_new_protected:Npn \multibox_do:nn #1 #2
 {
  \tl_set:Nn \l_multibox_tokens_tl { #2 }
  \prg_replicate:nn { #1 }
   {
    \tl_set:Nx \l_multibox_tokens_tl { \exp_not:N \fbox{ \exp_not:V \l_multibox_tokens_tl } }
   }
  \tl_use:N \l_multibox_tokens_tl
 }
\ExplSyntaxOff

\begin{document}
\multibox{5}{Hello}
\multibox{2}{world}
\end{document}

It shows an interesting feature: at each step of the replication, the previous content of \l_multibox_tokens_tl is expanded only once, even in a "complete expansion" context.

enter image description here

Let's see how it works. As the style guidelines recommend, the user level command \multibox is translated into a function, so the first definition is no mystery.

Next we reserve a token list variable that will be set to the text we want to box. After this assignment, we start a simple loop in which some code is repeated a number of times with \prg_replicate:nn{...}{...}. The first argument is the number of repetitions, the second is the code.

This is the important part: the token list variable is reset each time:

\tl_set:Nx \l_multibox_tokens_tl { <tokens> }

expands completely the <tokens> and stores the result in the token list variable. However, this "complete expansion" can be controlled: in this case we pass

\exp_not:N \fbox{ \exp_not:V \l_multibox_tokens_tl }

which means that \fbox will be stored as is (it's "\noexpand"); the open brace is already unexpandable like the closing brace. Now

\exp_not:V \l_multibox_tokens_tl

delivers the current value of the variable, but it will not expanded any more. So the successive values of \l_multibox_tokens_tl while executing \multibox{5}{Hello} will be

Hello
\fbox{Hello}
\fbox{\fbox{Hello}}
\fbox{\fbox{\fbox{Hello}}}
\fbox{\fbox{\fbox{\fbox{Hello}}}}
\fbox{\fbox{\fbox{\fbox{\fbox{Hello}}}}}

and this last value is finally delivered for typesetting.

Thus it's not really much different from Heiko's first solution, which uses token registers and \edef.

share|improve this answer
    
Thanks very much. Unfortunately, I understand this even less than the other two answers and so I think I'll stick to for loops for now. –  rbobbington Nov 18 '12 at 0:16

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.