# Different macro behavior when used in another macro

Please consider the following MWE :

\documentclass{article}

\newcommand{\mymargin}{\hspace*{3em}}
\newcommand{\innerbox}[1]{\mymargin\fbox{#1}\mymargin}
\newcommand{\outerbox}[1]{\fbox{#1}}

\begin{document}

test \innerbox{Hello} test% OK

test \outerbox{\innerbox{Hello} test \innerbox{Hello} test \innerbox{Hello}}%   I don't want space at beginning and end of box

test \outerbox{\fbox{Hello}\mymargin{} test \innerbox{Hello} test \mymargin\fbox{Hello}}%   what i'd like

\end{document}


(actually, the definitions of boxes are more complex but I think that doesn't change anything to the logic)

I'd like the use of \innerbox inside \outerbox not to induce spaces at the beginning and at the end of the box.

I suppose i should expand argument #1 (once got rid of the unnecessary spaces) from \outerbox and detect if the first and last token are equal \mymargin and then make the necessary changes but I really don't know how to do it. Any ideas?

You can check (ignoring spaces) whether the first token in the argument of \outerbox is \innerbox and, in this case, insert a negative space for compensation.

At the end you can recursively remove all glue nodes.

\documentclass{article}

\newcommand{\mymarginwidth}{3em}
\newcommand{\mymargin}{\hspace*{\mymarginwidth}}
\newcommand{\negmymargin}{\hspace*{-\mymarginwidth}}

\newcommand{\innerbox}[1]{\mymargin\fbox{#1}\mymargin}
\makeatletter
\newcommand{\outerbox}[1]{%
\fbox{%
\@ifnextchar\innerbox{\negmymargin}{}#1%
\forever@unskip
}%
}
\newcommand{\forever@unskip}{%
\ifnum\lastnodetype=11
\expandafter\unskip\expandafter\forever@unskip
\fi
}
\makeatother

\begin{document}

test \innerbox{Hello} test

test \outerbox{\innerbox{Hello} test \innerbox{Hello} test \innerbox{Hello}}

test \outerbox{\fbox{Hello}\mymargin{} test \innerbox{Hello} test \mymargin\fbox{Hello}}

test \outerbox{test \innerbox{Hello} test \innerbox{Hello}}

test \outerbox{\innerbox{Hello} test \innerbox{Hello} test}

test \outerbox{ test \innerbox{Hello} test \innerbox{Hello} }

test \outerbox{ \innerbox{Hello} test \innerbox{Hello} test }

\end{document}


• Thanks a lot, it works perfectly well... for this example of use. But, actually, \innerbox is defined with an optional argument (as \newcommand{\innerbox}[2][]{...}) and, in this case, your code leads to an error : ! Use of \\innerbox doesn't match its definition.. What should i change in your code to have it work ? Apr 17, 2019 at 11:41
• @user30654 Added the code Apr 17, 2019 at 16:01
• Your new code is all working fine, thank you very much ! Apr 18, 2019 at 14:28

This version omits the space if \innerbox is in any hbox, not just \outerbox

\documentclass{article}

\newcommand{\mymargin}{\hspace*{3em}}
\newcommand{\innerbox}[1]{\ifhmode\ifinner\else\mymargin\fi\fi\fbox{#1}\ifhmode\ifinner\else\mymargin\fi\fi}
\newcommand{\outerbox}[1]{\fbox{#1}}

\begin{document}

test \innerbox{Hello} test% OK

test \outerbox{\innerbox{Hello} test \innerbox{Hello} test \innerbox{Hello}}%   I don't want space at beginning and end of box

test \outerbox{\fbox{Hello}\mymargin{} test \innerbox{Hello} test \mymargin\fbox{Hello}}%   what i'd like

\end{document}


egreg notes that you may not be what you wanted, so..

\documentclass{article}

\newcommand{\mymargin}{\hspace*{3em}}
\newcommand{\innerbox}[1]{\ifhmode\ifnum\lastpenalty=-1\else\mymargin\fi\fi\fbox{#1}\mymargin}
\newcommand{\outerbox}[1]{\fbox{\penalty-1#1\unskip\unskip}}

\begin{document}

test \innerbox{Hello} test% OK

test \outerbox{\innerbox{Hello} test \innerbox{Hello} test \innerbox{Hello}}%   I don't want space at beginning and end of box

test \outerbox{\fbox{Hello}\mymargin{} test \innerbox{Hello} test \mymargin\fbox{Hello}}%   what i'd like

\end{document}

• Which is rather different from the output the OP seems to want. Look at the “what I'd like” line. Apr 16, 2019 at 16:51
• @egreg 2nd version added (shame, first version was more fun) Apr 16, 2019 at 17:49