9

\centerline is the same as \line{\hss#1\hss}

Then why in the next example in the \line case the space is visible, and in \centerline case it is not? In both cases space has correct catcode 12.

\catcode`\"=\active
\def"{\leavevmode\hbox\bgroup\let"=\egroup\catcode`\ =12\tt}
\line{\hss"hello world\the\catcode`\ "\hss}
\centerline{"hello world\the\catcode`\ "}
\bye

enter image description here

  • 2
    Because in the centerline case your hello world is the argument of a macro, and so gets tokenized all immediately. – User Jul 4 '16 at 5:57
  • 3
    For the record: this is mentioned on page 48 of TeXbook. – Igor Liferenko Jul 4 '16 at 6:16
3

Some complements to wipet's good answer.

The definitions in plain.tex are as follows (lines 575–578):

\def\line{\hbox to\hsize}
\def\leftline#1{\line{#1\hss}}
\def\rightline#1{\line{\hss#1}}
\def\centerline#1{\line{\hss#1\hss}}

You can notice that \line is just shorthand for \hbox to\hsize, so the call

\line{\hss"hello world\the\catcode`\ "\hss}

becomes

\hbox to\hsize{\hss"hello world\the\catcode`\ "\hss}

One might think that such a call will obey the same rules as

\centerline{\hss"hello world\the\catcode`\ "\hss}

that is, {\hss"hello world\the\catcode`\ "\hss} is absorbed as an argument to \hbox, but there's a fundamental difference between the two cases.

You should be aware of this, because you're defining active " to do \hbox\bgroup and macros taking an argument don't allow such a syntax for denoting the start of the argument. On page 278 of the TeXbook, you find the syntax for \hbox:

\hbox⟨box specification⟩{⟨horizontal mode material⟩}

and such notation means that the braces can also be implicit characters having category code 1 and 2 respectively. In these cases, the material inside these braces is only scanned after { is processed (here, also after the material in \everyhbox and possibly \afterassignment has been inserted). The matching } will start the operation of converting the horizontal list into a box.

In particular,

\hbox{\catcode`\ =12 a b}

will perform the category code assignment and the space will be absorbed with category code 12.

To the contrary, \centerline{\catcode`\ =12 a b} will absorb the argument tokenizing it (as explained by Petr). When TeX is absorbing an argument, it performs no expansion and no assignment; if the argument is undelimited (as in the case of \centerline), the argument will be the next token (after skipping explicit space tokens) unless this token is a left brace (explicit character with category code 1), when the argument will be the tokens up to the matching right brace (explicit character with category code 2). Tokenization is performed, so the spaces will be of category code 10.


Is it possible to solve this problem? Yes, with e-TeX.

\catcode`\"=\active
\def"#1"{%
  \leavevmode\hbox{%
    \catcode`\ =12
    \tt
    \scantokens{#1\relax}%
  }%
}

\line{\hss X"hello world"X\hss}
\centerline{X"hello world"X}
\bye

enter image description here

  • It seems that there is one redundant \noexpand. Really, I don't understand why. – wipet Jul 4 '16 at 20:22
  • @wipet Try without it and enjoy the space between d and X. The space comes from the fact that TeX implicitly adds and \endlinechar at the end of every input file and \scantokens is realized by inputting a “virtual file”. A misfeature, certainly, but that's what it is. – egreg Jul 4 '16 at 20:31
  • OK, why explicitly \noexpand? For example, \relax is sufficient. Your \noepand does no-expanding of the closing brace at the line 7 of your code. This is obscure. – wipet Jul 5 '16 at 4:15
  • @wipet I learned it some years ago on comp.text.tex; and, no, it doesn't act on the brace, as far as I know. – egreg Jul 5 '16 at 8:00
  • Using \noexpand is totally irrelevant here. \relax or \empty is sufficient. This \noexpad does no-expansion of the brace (which closes \hbox) and this does nothing special in your code, of course. But, try to insert \iffase xxx\fi before this closing brace. Then \iffalse is no-expanded and extra \fi error occurs. – wipet Jul 5 '16 at 14:44
13

\centerline is defined by \def\centerline#1{\line{\hss#1\hss}} but \line is defined by \def\line{\hbox to\hsize}. It means that \line{next text} does not take the next text as parameter. The next text is processed inside \hbox primitive in main processor of TeX. If there is an assignment (like \catcode setting) then this is done immediately and then next characters are read (and tokenized). On the other hand, \centerline{next text} reads the next text as a parameter first. All characters are tokenized in this state, but assignment is not done. After parameter is read and tokenized then in is used in the context \hbox...{..next text..} but all characters are tokenized here. So, \catcode setting has no effect now. Only, of course, the \the\catcode report is changed. This report prints the value used by token processor for next characters, which are not tokenized already.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.