On this post, one answer states that \obeylines is defined as

\def\obeylines{\catcode`\^^M\active \let ^^M\par }

However TeX complains when I try to compile the following code

\def\obeylines{\catcode`\^^M\active \let ^^M\par }
\def\disobeylines{\catcode`\^^M=5 }

    We obey, and end up on separate lines.
    We obey.
We disobey, and end up on the same line.
We disobey.


The situation doesn't get any better when I change the first line to

\def\obeylines{\catcode`\^^M=13 \let^^M=\par }

Why is this code not working?

  • 4
    This question could probably do with a better title.
    – Werner
    Commented Apr 5, 2018 at 15:56
  • You don't need to define \obeylines, do you?
    – egreg
    Commented Apr 5, 2018 at 16:31

2 Answers 2


When TeX performs a \def, it just stores tokens with their current category code. In your case you are storing

\catcode`12\^^M\active\let ^^M5\par

(bullets separate tokens). So when your \obeylines macro is called, ^^M becomes active, but \let^^M will throw an error of “Missing control sequence”.

Actually, this analysis is not the full truth, because the ^^M with category code 5 in the body of the definition will cause the line to be finished and \par} ignored. So the error you get is different. Doing similar things with other characters would have the same problem described above.

If you look in plain.tex you see

% In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}'
% since this allows, for example, `\let\par=\cr \obeylines \halign{...'
{\catcode`\^^M=\active % these lines must end with %
  \gdef\obeylines{\catcode`\^^M\active \let^^M\par}%
  \global\let^^M\par} % this is in case ^^M appears in a \write

so what's actually stored is

\catcode`12\^^M\active\let ^^M13\par

which does the job. The \global\let^^M\par can be without the \global, but you could incur into problems if page breaks come along.

  • Thanks to you: now I know of the existence of plain.tex. Very good answer.
    – Lagrang3
    Commented Apr 5, 2018 at 16:52
  • @egreg The \global\let^^M\par can be without the \global, but you could incur into problems if page breaks come along. You must have been thinking about something related (contents of \obeylines will be interrupted by a page break?) but distinct, because the \global in your quote of plain.tex is simply there to give some definition to the active ^^M, and it wouldn't have any effet without \global.
    – user4686
    Commented Apr 8, 2018 at 21:37

You need ^^M to be active at time of definition, in order for the \let^^M\par to be legal. Check plain.tex for one way.

  • First of all, thanks for the answer. I don't understand: isn't \catcode`\^^M=13 making it active?
    – Lagrang3
    Commented Apr 5, 2018 at 16:18
  • @Lagrange.el.Ciencia No, it only does when \obeylines is called; but you need ^^M to be active in order to do \let^^M=\par and it isn't if the definition is not made when ^^M is active.
    – egreg
    Commented Apr 5, 2018 at 16:30
  • @egreg Now I see. I did this: \catcode`\^^M=13\def\obeylines{\catcode`\^^M=13 \let ^^M=\par }\catcode`\^^M=5 and it worked!
    – Lagrang3
    Commented Apr 5, 2018 at 16:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .