Wie schreibt man ein Makro, das Argumente mit Absätzen annimmt?

Wie schreibt man ein Makro, das Argumente mit Absätzen annimmt?

Ich versuche, ein Makro zu schreiben, das Argumente mit Absätzen akzeptiert. Wenn Sie ein normales Makro schreiben und eines seiner Argumente einen Absatz enthält, wird es unterbrochen:

\documentclass{article}
\usepackage[utf8]{inputenc}

\title{test}

\begin{document}

\maketitle

\section{Introduction}

\def\mymacro#1{#1}

\mymacro{This

contains a paragraph}

\end{document}

Dies führt zu einem Fehler:

Runaway argument?
{This
! Paragraph ended before \mymacro was complete.
<to be read again> 
                   \par
l.15

Also habe ich versucht, \pardie Argumente des Makros zum Erweitern neu zu definieren, aber jetzt wird die Kompilierung nicht mehr gestoppt:

\documentclass{article}
\usepackage[utf8]{inputenc}

\title{test}

\begin{document}

\maketitle

\section{Introduction}

\gdef\oldpar{\par}

\def\mymacro{\gdef\par{}\mymacroi}

\def\mymacroi#1{#1\gdef\par{\oldpar}}

\mymacro{foo

bar}

\end{document}

Antwort1

Als TeX geschrieben wurde, dauerte die Verarbeitung einer Seite eines Dokuments mehrere Minuten und Syntaxhervorhebung war noch nicht möglich. Daher war es gut, einen Mechanismus zu haben, der erkennt, ob man ein vergessen hat }. Ein \deflässt standardmäßig kein \parToken zu, es sei denn, man gibt explizit an, dass es ein ist \long\def:

\def\mymacro#1{#1}

LaTeX hingegen verwendet dies standardmäßig. Wenn Sie also die richtigen LaTeX-Befehle verwenden ( \defsollte nicht in LaTeX-Dokumenten verwendet werden), wird standardmäßig \newcommandein erstellt . Wenn Sie ein „kurzes“ möchten , verwenden Sie .\long\def\def\newcommand*

xparsegibt das kurze Argument default zurück, ermöglicht Ihnen aber, ein \longMakro mit dem +Argumentmodifikator zu definieren:

\NewDocumentCommand\mymacro{ m}{#1}% \def
\NewDocumentCommand\mymacro{+m}{#1}% \long\def

Ihr zweiter Versuch ist geschickt und hätte funktionieren können, wenn da nicht zwei Dinge wären.

Zuerst verwenden Sie \gdef\oldpar{\par}und dann\gdef\par{\oldpar} . Sobald Sieexpandieren \parSie erhalten, \oldparwas, wenn erweitert, ergibt, \parwas, wenn erweitert, ergibt, \oldparwas, wenn erweitert, ergibt, \parwas, wenn erweitert, ergibt \oldpar... Läuft ewig :/

In diesem Fall müssen Sie Folgendes verwenden \let(oder um eine globale Wirkung zu erzielen): . Dadurch wird eine genaue Kopie von „named“ erstellt , die nicht davon abhängt, was „named“ ist .\global\let\let\oldpar\par\par\oldpar\par

Zweitens wird die Überprüfung auf außer Kontrolle geratene Argumente auf einer niedrigeren Ebene implementiert, unabhängig von der Definition von \par, sodass dies mit demselben Fehler fehlschlagen würde:

\let\par\relax
\def\mymacro#1{#1}
\mymacro{foo

bar}

denn wenn TeX zwei \endlinecharToken sieht (was standardmäßig ein Leerzeichen ist), fügt TeX ein implizites \parToken ein, was den Runaway argumentFehler auslöst. Wenn man das weiß, dann:

\newcount\oldELchar
\oldELchar=\endlinechar
\def\mymacro{\endlinechar=-1\relax\mymacroi}
\def\mymacroi#1{#1\endlinechar=\oldELchar}
\mymacro{foo

bar}

wird keinen Fehler auslösen, aber eine neue Zeile wird kein Leerzeichen mehr sein.

Antwort2

Das Argument eines mit definierten Makros \deferlaubt keine \parToken. Es erlaubt auch keine Leerzeilen, da diese \parwährend der Phase, in der TeX Texteingaben in Tokens verarbeitet, in umgewandelt werden. Beachten Sie, dass eine Neudefinition \parin dieser Hinsicht nutzlos ist, da esgenaudas Token \par, das nicht zulässig ist, unabhängig von seiner Bedeutung.

Lösung: Erstellen Sie Ihr Makro \long.

\long\def\mymacro#1{#1}

Bessere Lösung:

\newcommand{\mymacro}[1]{#1}

weil intern \newcommandverwendet wird \long\def. Die Variante \newcommand*verwendet stattdessen \defohne das Präfix.

verwandte Informationen