4

I'm trying to create a command we can use for comments in our document. During development, we want the comments to appear; for production, we want them to disappear. This is a common enough problem with many solutions.

I'm having an issue with LaTeX's tokenizer, though; if the command is surrounded by spaces, two spaces are emitted. I understand why that's happening, but none of the workarounds that I can find are any good for me. Here's a representative example.

\documentclass[letterpaper]{article}

\newif\ifnotes
\newcommand{\note}[1]{\ifnotes{#1}\fi}
\notesfalse
\newcommand{\nonotes}{\notesfalse}

\begin{document}
\pagestyle{empty}

Testing \note{X} testing testing.

\end{document}

Because \notesfalse has been invoked, the note should not (and does not) appear. But the spaces to the left and right of the command do appear, which is a problem for me.

I could modify the command to eat all of the spaces after it, but this isn't really the correct behavior either; if the command only has spaces following (as in the\note{...} text), there should still be an emitted space. While I know that one can use things like \unskip to delete preceding space, I'm at a loss to detect the preceding (and following) space so I can make an intelligent decision about whether it should stick around.

Does anyone have any suggestions for accomplishing this task?

tvynr
  • 85
  • 3
  • 1
    you could redefine \note to be {\unskip\ \ignorespaces} but you might also need to test whether you're in horizontal mode. (i don't remember whether the space-eating commands complain if the command is launched in vertical mode, and don't have time to experiment.) – barbara beeton Feb 16 '16 at 19:12

1 Answers1

7

Here is a solution

\documentclass[letterpaper]{article}

\newif\ifnotes
\makeatletter
\newcommand{\note}[1]{\@bsphack\ifnotes{#1}\fi\@esphack}
\makeatother
\notesfalse
\newcommand{\nonotes}{\notesfalse}

\begin{document}
\pagestyle{empty}

Testing \note{X} testing testing.

Testing\note{X} testing testing.

Testing \note{X}testing testing.

Testing\note{X}testing testing.

\notestrue

Testing \note{X} testing testing.

Testing\note{X} testing testing.

Testing \note{X}testing testing.

Testing\note{X}testing testing.

\end{document}

enter image description here

touhami
  • 19,520
  • 1
    Not only a solution, the solution provided by LaTeX. – Manuel Feb 16 '16 at 19:20
  • @Manuel yes you're right. – touhami Feb 16 '16 at 19:25
  • 1
    Mmm… in fact \@bsphack\@esphack only should be in case \notesfalse. – Manuel Feb 16 '16 at 19:49
  • @Manuel I am not sure I undestand why? – touhami Feb 16 '16 at 20:16
  • 2
    I agree with @Manuel on this one; there's a subtlety that requires the hack to be avoided when notes are enabled. The reason is actually in your output: on the fifth line, the X should have spaces both before and after it.

    That said, \newcommand{\note}[1]{\ifnotes{#1}\else\@bsphack\@esphack\fi} is exactly what I wanted! Thanks!

    – tvynr Feb 16 '16 at 21:25
  • @tvynr By the way, the braces around #1 are not required, you should remove them unless you actually want them there \newcommand*\note[1]{\ifnotes#1\else\@bsphack\@esphack\fi}. – Manuel Feb 16 '16 at 21:42
  • I should probably mention here that http://tex.stackexchange.com/questions/294693/multiple-space-hacks-generate-more-space includes a fix for the case in which two notes are adjacent to each other. – tvynr Mar 01 '16 at 18:27