7

I've written several LaTeX environments to format a "use case flow" sequence for a college project. Being a computer programmer, I find quite annoying to not be able to use newlines and indentation (like C/Java code) to format the LaTeX code and make it more readable, as I know I must be aware of the "spurious spaces" problem. I know I can make safe newlines using %, but it's still quite weird.

Then, I remembered that each character read by TeX has assigned a 'catcode' that governs its behavior, and there's a catcode for characters that must be ignored (9). So, I had the idea of changing temporally the catcodes for newlines and tabs (that will be used for code formatting) and ignore them while the macros are being defined. For example, this code:

% UCSubFlow counter definition, etc
\newenvironment{subflow}[1]{%
\subparagraph{Subflow \arabic{UCSubFlow}: #1}%
\stepcounter{UCSubFlow}%
\begin{enumerate}%
}{%
\end{enumerate}%
}

becomes the, IMO, more pleasing to read:

% Ignore tabs and newlines
\catcode9=9
\catcode13=9

% UCSubFlow counter definition, etc
\newenvironment{subflow}[1]{
    \subparagraph{Subflow \arabic{UCSubFlow}: #1}
    \stepcounter{UCSubFlow}
    \begin{enumerate}
}{
    \end{enumerate}
}
% More macro definitions...

% Return tabs and newlines back to normal
\catcode9=10
\catcode13=5

The spacing at the start of the line are tabs, not spaces (they are still used). I'm assuming that:

  • Most of the time, macros don't use <tab>s in its definition
  • Most of the time, macros don't have large paragraphs of text. If I want to start a paragraph in my macro, it's better to use \par
  • Macros always can be written in one line (very long ones, but one line anyway)

I've used it in my document and it seems to be all OK. The environment works as expected and it doesn't seems to have broken anything. Granted, my environment is quite simple (an special list). My question is: is this 'hack' safe in general when it comes to macro writing, of there is some hidden danger? (specially if I use other packages' macros inside my macro)

lartkma
  • 171

1 Answers1

3

First of all, your intend can be realized simple by setting \endlinechar=-1. You needn't to set catcode for ^^M because \endlinechar-1 causes that this character isn't inserted. You needn't to set catcode for ^^I (tab) because spaces and tabs have catcode 10 and they are simply ignored at the beginning of each line.

But this setting is dangerous. Of course, this can't be put it in normal text of document, because after:

 Hello
 world!

we get Helloworld! as the result. And the usage of this setting only during macro reading? Imagine the definition:

\def\a{Hello
       world!}

then the same problem as above occurs. And the problem can be more hidden, for example:

\def\b{\ifnum\something=0
            123%
        \else
            456%
        \fi
}

Now, if the space is present at the end of each line then we have if(somenthing=0) 123 else 456 fi but if the space isn't present here then we have if(something=0123) else 456 fi and this is completely different behavior of such macro.

wipet
  • 74,238
  • Indeed! In expl3 the character ~ is given category code 10 for making it useful in situations like the last one; \ifnum\something=0~ would solve the issue. Note that TeX won't strip off the trailing ~ when reading the line (because it's not a space or tab) and then will normalize the funny space to an ordinary space token. However, in expl3 constants will always be braced, so the problem doesn't really arise. – egreg May 03 '15 at 09:26
  • \ifnum\something=0\space or \ifnum\something=0 % would solve the issue too and I needn't to use expl3. But my comment was about the reasons why setting \endlinechar=-1 is dangerous when it is applied to unknown macro code. There is numerous other situations where the space in macro code (maybe generated from the endline) is very important. – wipet May 03 '15 at 10:03
  • 2
    I don't understand why you're always looking for polemic at all costs. I was commenting favorably your answer after upvoting it, adding a comparison with what expl3 does in order to avoid the same problem. – egreg May 03 '15 at 12:51