# How to make a command completely empty / invisible / non-existent?

I have a command like

\newcommand{\todo}[1]{#1}


which I sometimes replace by:

\newcommand{\todo}[1]{}


In terms of spacing/whitespace, the behavior of the "empty" command is as follows:

Test.

\todo{foo} % does not generate (vertical) whitespace => good

Test\todo{foo}. Test. % does not generate (horizontal) whitespace => good

Test\todo{foo}. \todo{foo} Test. % _does_ generate (horizontal) whitespace => bad


Is there any way to avoid this, i.e., to (temporarily) replace a command in a way so that it is fully equivalent to removing all occurrences of the command?

(I know that there are packages like todonotes or verbatim, which provide similar functionality. But I always wanted to know how to solve this manually, and never had an idea how to approach this / what to search for. Using \xspace or \empty in the command did not work at least.)

• – Werner Sep 20 '14 at 5:56

The classical way is using \@bsphack and \@esphack. They are used by \label or \index, both supposed to be invisible/empty regarding spacing. These commands remember, if there is a space before the command. If yes, the second space afterwards is suppressed by \ignorespaces. The commands are defined in the LaTeX kernel:

\def\@bsphack{%
\relax
\ifhmode
\@savsk\lastskip
\@savsf\spacefactor
\fi}
\def\@esphack{%
\relax
\ifhmode
\spacefactor\@savsf
\ifdim\@savsk>\z@
\ignorespaces
\fi
\fi}


Applied to \todo:

\documentclass{article}

\makeatletter
\newcommand{\todo}[1]{%
\@bsphack
\@esphack
}
\makeatother

\begin{document}
Test.

\todo{foo}

Test\todo{foo}. Test.

Test\todo{foo}. \todo{foo} Test.
\end{document}


Limitation: The method can fail, if the macros using \@bsphack and \@esphack are used one after each other. The second \@bsphack does not know the state of the previous one. Therefore \ignorespaces can be suppressed leaving the following space.

• Works like a charm, thanks! Apparently, the occurrence of a command will internally never be equivalent to the case of a "non-occurrence". So I guess the best solution here is to emulate the non-occurrence. – bluenote10 Sep 18 '14 at 12:39

It doesn't really generate space it's just that you have added two spaces, you would see same from a {} b with one space before and one after. But you can end your command with \ignorespaces to ignore the following space.

\newcommand{\todo}[1]{\ignorespaces}

• This is looking good, but: In this case Test\todo{foo}.\todo{foo} Test. behaves "unexpected", since it is not the same as Test\todo{foo}. Test. -- any idea to solve this as well? – bluenote10 Sep 18 '14 at 12:15
• @bluenote10 \ignorespaces is simpler, the more complicated thing is to see if there was a space before and just ignorespaces in that case) that's what the latex \@bspack macro does (it is used in \label{} and \index{] and similar commands that are supposed to be "invisible"). I thought I'd just do the simple one, but if you want the other, give the tick to Heiko:-) – David Carlisle Sep 18 '14 at 12:32
• Thanks for the clarification! Considering the educational aspect of my question, your answer is highly appreciated :). – bluenote10 Sep 18 '14 at 12:35

You put nothing into the horizontal/vertical list when \toto is empty. Thus the \spacefactor manipulating is redundant (see the accepted answer). The following code is sufficient for this task:

\def\hideme{\ifdim\lastskip>0pt \ignorespaces\fi}
\def\todo#1{#1}
% or:
\def\todo#1{\hideme}