At the time TeX was written, one page of a document would take several minutes to be processed, and syntax highlighting was not a thing, so it was a good thing to have some mechanism to detect if you forgot a }
. A \def
, by default, doesn't allow a \par
token unless you explicitly say it's a \long\def
:
\def\mymacro#1{#1}
LaTeX, on the other hand, uses that by default, so if you use proper LaTeX commands (\def
shouldn't be used in LaTeX documents), \newcommand
makes a \long\def
by default. If you want a “short” \def
then you use \newcommand*
.
xparse
returns the short argument default, but lets you define a \long
macro using the +
argument modifier:
\NewDocumentCommand\mymacro{ m}{#1}% \def
\NewDocumentCommand\mymacro{+m}{#1}% \long\def
Your second attempt is clever, and it could have worked except for two things.
First is that you are using \gdef\oldpar{\par}
and then \gdef\par{\oldpar}
. Once you expand \par
you get \oldpar
which, when expanded, yields \par
which, when expanded, yields \oldpar
which, when expanded, yields \par
which, when expanded, yields \oldpar
... Running forever :/
You need to use \let
(or \global\let
to have global effect) in this case: \let\oldpar\par
. This creates an exact copy of \par
named \oldpar
which does not depend on what is \par
.
Second, the runaway argument checking is implemented in a lower level, independent of the definition of \par
, so this would fail with the same error:
\let\par\relax
\def\mymacro#1{#1}
\mymacro{foo
bar}
because when TeX sees two \endlinechar
tokens (which is a space by default) TeX inserts an implicit \par
token, which raises the Runaway argument
error. Knowing that, then:
\newcount\oldELchar
\oldELchar=\endlinechar
\def\mymacro{\endlinechar=-1\relax\mymacroi}
\def\mymacroi#1{#1\endlinechar=\oldELchar}
\mymacro{foo
bar}
won't raise an error, but a new line won't be a space anymore.
\long\def
or\newcommand
.\def
is not a latex command,\newcommand
which, is already allows paragraphs.