[ Dieses Posting supersedet mein Posting
< news:m76d3f$k7l$***@news.albasani.net >
vom 21 Dezember 2014, 13:04:29 (MEZ) . ]
Post by BaÅar AlabayUff … also, das ganze Folgende ist mir dann doch zu hoch gewesen :-)
============================================================
Kurzanleitung:
============================================================
Das, was den Mechanismus ausmacht, steht zwischen
\makeatletter und \makeatother.
-----------------------------------------------------------------
Der Mechanismus bietet zwei Befehle an:
\MyIncludeCommentmarkerCommand{<Kontrollsequenz-Token>}
und
\MyExcludeCommentmarkerCommand{<Kontrollsequenz-Token>}
Mit diesen Befehlen kann man Makros definieren.
-----------------------------------------------------------------
Wenn man schreibt:
\MyIncludeCommentmarkerCommand{\foo}%
, dann wird ein Makro \foo definiert.
Dieses Makro \foo schaltet temporär auf Verbatim-Catcodes um und liest
entweder nach der Syntax des \verb-Befehls ein Argument ein oder liest
ein in geschweifte Klammern eingefasstes Argument ein.
Dieses Argument wird dann mittels des Befehls "\scantokens" ausgegeben
und dabei mit dem normalen Catcode-Régime neu getokenized.
Nach
\MyIncludeCommentmarkerCommand{\foo}%
kannst Du (-> \verb-Syntax) zB schreiben:
Bla bla \foo|Satzteil wird jetzt ausgegeben |bla bla.
oder auch (-> Argument in geschweiften Klammern):
Bla bla \foo{Satzteil wird jetzt ausgegeben }bla bla.
Das macht unter normalen catcode-Bedingungen keinen Unterschied.
Das Ergebnis wird in beiden Fällen (hoffentlich) sein:
Bla bla Satzteil wird jetzt ausgegeben bla bla.
Im Argument von \foo kannst Du auch \verb-Befehle oder verbatim-Umgebungen
oder lstlisting-Umgebungen und dergleichen nutzen.
\outer-Token und Absatzumbrüche und dergleichen dürfen im Argument
von \foo auch vorkommen.
-----------------------------------------------------------------
Wenn man schreibt:
\MyExcludeCommentmarkerCommand{\foo}%
, dann wird ein Makro \foo definiert.
Dieses Makro \foo schaltet temporär auf Verbatim-Catcodes um und liest
entweder nach der Syntax des \verb-Befehls ein Argument ein oder liest
ein in geschweifte Klammern eingefasstes Argument ein.
Dieses Argument wird dann "verschluckt".
Nach
\MyExcludeCommentmarkerCommand{\foo}%
kannst Du zB schreiben:
Bla bla \foo|Satzteil wird jetzt nicht ausgegeben |bla bla.
oder auch:
Bla bla \foo{Satzteil wird jetzt nicht ausgegeben }bla bla.
Das macht unter normalen catcode-Bedingungen keinen Unterschied.
Das Ergebnis wird in beiden Fällen (hoffentlich) sein:
Bla bla bla bla.
Im Argument von \foo kannst Du auch \verb-Befehle oder verbatim-Umgebungen
oder lstlisting-Umgebungen und dergleichen nutzen.
\outer-Token und Absatzumbrüche und dergleichen dürfen im Argument von
\foo auch vorkommen.
-----------------------------------------------------------------
Summa sumarum:
Mit
\MyIncludeCommentmarkerCommand{\foo}
bzw
\MyExcludeCommentmarkerCommand{\foo}
kannst Du einen Befehl \foo (um)definieren und gleichzeitig
festlegen (bzw hin- und herschalten), ob dieser Befehl sein
Argument ausgibt oder "verschluckt".
Der Befehl \foo schaltet temporär auf Verbatim-Catcodes um und liest
entweder nach der Syntax des \verb-Befehls ein Argument ein oder liest
ein in geschweifte Klammern eingefasstes Argument ein.
Deshalb kannst Du im Argument von \foo auch \verb-Befehle oder
verbatim-Umgebungen oder lstlisting-Umgebungen und dergleichen nutzen.
\outer-Token und Absatzumbrüche und dergleichen dürfen im Argument
von \foo auch vorkommen.
Da \foo sein Argument mit Verbatim-Catcode-Régime einliest,
kannst Du allerdings - genau wie beim \verb-Befehl - im Argument von
\foo eine Zeile nicht mit Kommentarzeichen oder mit catcode-5-Zeichen
komplett beenden, da zum einen diese Zeichen im Verbatim-Catcode-Régime nicht
als Kommentarzeichen bzw Zeilenbeendungszeichen interpretiert
werden, und zum anderen \scantokens, welches dann beim erneuten
Tokenizen diese Zeichen wieder mit dem üblichen catcode-Régime
interpretiert, nur auf das Argument von \foo losgelassen wird, und nicht
auf das, was im Quelltext dahinter steht.
ZB wird mit
\MyIncludeCommentmarkerCommand{\foo}%
...
Bla bla \foo{Satzteil wird jetzt %ausgegeben }bla bla.
das Ergebnis sein:
Bla bla Satzteil wird jetzt bla bla.
-----------------------------------------------------------------
Mir ist übrigens eben eine Unzulänglichkeit an meinem
Mechanismus aufgefallen:
Im Falle von \MyIncludeCommentmarkerCommand wird das
verbatimisiert eingelesene Argument von \foo an \scantokens
weitergereicht.
\scantokens wiederum tut so, als ob dieses Argument unexpandiert
in eine externe Datei geschrieben und dann aus dieser Datei wieder
eingelesen würde.
Beim "Wiedereinlese-Vorgang" steht der Status des Leseapparatus
von TeX zunächst auf "Neue Zeile einlesen".
Wenn der Leseapparatus von TeX auf "Neue Zeile einlesen" steht,
werden eingelesene Leerzeichen nicht zu Space-Token, sondern
ignoriert.
Ich habe übersehen, dass man deshalb Leerzeichen, die im Argument
von \foo ganz am Anfang stehen, verliert.
Mit
\MyIncludeCommentmarkerCommand{\foo}%
...
Bla bla\foo{ Satzteil wird jetzt ausgegeben }bla bla.
wird das unschöne Ergebnis sein:
Bla blaSatzteil wird jetzt ausgegeben bla bla.
Eigentlich sollte es sein:
Bla bla Satzteil wird jetzt ausgegeben bla bla.
Hier kommt die korrigierte Fassung meines Mechanismus, bei der
dies nicht mehr der Fall ist, weil ich am Anfang des Arguments der
entsprechenden \scantokens-Anweisung die Anweisung
"\csname @firstofone\endcsname{csname @esphack\endcsname}"
hineingeflickt habe sodass
beim "Wiedereinlesevorgang" die Zeile mit
\csname @firstofone\endcsname{csname @esphack\endcsname}"
-> \@firstofone{csname @esphack\endcsname}
-> csname @esphack\endcsname
-> \@esphack
anfängt und nicht mit Leerzeichen, die womöglich ignoriert
werden würden.
Ausserdem habe ich die Kommentare für die Handhabung von
\UDverbarg korrigiert.
\documentclass{article}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% June 25, 2013 / by Ulrich Diez (***@web.de) / License: LPPL.
%
% Stuff for reading arguments "verbatim":
%
% Syntax of \UDverbarg:
%
% \UDverbarg{<^^M-replacement>}{<Mandatory 1>}{<Mandatory 2>}<verbatim-Arg>
%
% yields:
%
% <Mandatory 1>{<Mandatory2>{<verbatim-Arg>}}
%
% with each character ^^M (usually=\endline-char) replaced by
% token-sequence <^^M-replacement>
%
% The Mandatory-Arguments are mandatory.
% If reading is necessary, they will be read under current/unchanged
% catcode-conditions.
% The <verbatim-Arg> is also mandatory. It will be read under
% verbatim-catcode-conditions. If its first character is a brace,
% it will be "assumed" that the argument is nested into braces.
% Otherwise it will be assumed, that the argument is delimited
% by the first character - like the argument of \verb.
%
% Empty lines will not be ignored.
%
% By nesting calls to \UDverbarg within \UDverbarg's <Mandatory-1>-
% argument, you can collect "verbatim-arguments" within the
% <Mandatory-2>-argument.
%
% E.g.,
%
% \UDverbarg{<^^M-replacement>}% <- ^^M-replacement
% {\UDverbarg{<^^M-replacement>}{\UDverbarg{<^^M-replacement>}{<actionA>}}}% <- Mandatory 1
% {<actionB>}% <- Mandatory 2
% <verbatim-Arg1><verbatim-Arg2><verbatim-Arg3>
%
% yields:
%
% \UDverbarg{<^^M-replacement>}% <- ^^M-replacement
% {\UDverbarg{<^^M-replacement>}{<actionA>}}% <- Mandatory 1
% {<actionB>{<verbatim-Arg1>}}% <- Mandatory 2
% <verbatim-Arg2><verbatim-Arg3>
%
% yields:
%
% \UDverbarg{<^^M-replacement>}% <- ^^M-replacement
% {<actionA>}% <- Mandatory 1
% {<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}}% <- Mandatory 2
% <verbatim-Arg3>
%
% yields:
%
% <actionA>{<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}}
%
% Assume <actionA> = \@firstofone -> equals:
%
% \@firstofone{<actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}}
%
% yields:
%
% <actionB>{<verbatim-Arg1>}{<verbatim-Arg2>}{<verbatim-Arg3>}
%
\begingroup
\catcode`\^^M=12 %
\@firstofone{%
\endgroup%
\newcommand*\UDEndlreplace[2]{%
\romannumeral0\@UDEndlreplace{#2}#1^^M\relax{}%
}%
\newcommand\@UDEndlreplace{}%
\def\@UDEndlreplace#1#2^^M#3\relax#4#5{%
\ifx\relax#3\relax%
\expandafter\@firstoftwo%
\else%
\expandafter\@secondoftwo%
\fi%
{ #5{#4#2}}{\@UDEndlreplace{#1}#3\relax{#4#2#1}{#5}}%
}%
}%
\newcommand\UDverbarg[3]{%
\@bsphack
\begingroup
\let\do\@makeother\dospecials
\catcode`\{=1 %
\catcode`\ =10 %
\@ifnextchar\bgroup
{\catcode`\}=2 \@UDverbarg{#1}{#2}{#3}{}}%
{\do\{\@UDverbarg{#1}{#2}{#3}}%
}%
\newcommand\@UDverbarg[4]{%
\do\ %
\catcode`\^^M=12 %
\long\def\@tempb##1#4{%
\edef\@tempb{##1}%
\@***@sanitize\@tempb
\expandafter\UDEndlreplace\expandafter{\@tempb}{#1}{\def\@tempb}%
\expandafter\@@UDverbarg\expandafter{\@tempb}{#2}{#3}%
}%
\@tempb
}%
\newcommand\@@UDverbarg[3]{%
\endgroup
\@esphack
#2{#3{#1}}%
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newcommand*\UDRemoveTillCharacterMarker{%
\@bsphack\UDverbarg{^^J}%
{\@firstoftwo{\@esphack}}%
{}%
}%
\newcommand\UDCallScantokens[1]{%
\scantokens{%
\csname @firstofone\endcsname
{\csname @esphack\endcsname}%
#1%
\endinput
}%
}%
\newcommand*\UDKeepTillCharacterMarker{%
\@bsphack\UDverbarg{^^J}%
{\@firstofone}%
{\UDCallScantokens}%
}%
\newcommand\MyIncludeCommentmarkerCommand[1]{%
\global\let#1=\UDKeepTillCharacterMarker
}%
\newcommand\MyExcludeCommentmarkerCommand[1]{%
\global\let#1=\UDRemoveTillCharacterMarker
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatother
\MyIncludeCommentmarkerCommand{\CommentMarkerA}
%\MyExcludeCommentmarkerCommand{\CommentMarkerA}
\MyExcludeCommentmarkerCommand{\CommentMarkerB}
%\MyIncludeCommentmarkerCommand{\CommentMarkerB}
\begin{document}
Bla bla\CommentMarkerA{ Blubb% Blebb} Bla bla.
Bla bla\CommentMarkerA| Blubb% Blebb| Bla bla.
Bla bla\CommentMarkerB{ Blubb% Blebb} Bla bla.
Bla bla\CommentMarkerB| Blubb% Blebb| Bla bla.
\bigskip
Bla bla\CommentMarkerA{ Blubb Blebb} Bla bla.
Bla bla\CommentMarkerA| Blubb Blebb| Bla bla.
Bla bla\CommentMarkerB{ Blubb Blebb} Bla bla.
Bla bla\CommentMarkerB| Blubb Blebb| Bla bla.
\bigskip
Hier ein Beispiel mit \texttt{\string\verb}-Syntax:
Normaler Text A. \CommentMarkerA~Das bleibt. Das
bleibt. ~Normaler Text A. Normaler Text A. \CommentMarkerA|Das bleibt.
Und der naechste Absatz auch:
Hier ist der naechste Absatz. Auch \texttt{\string\verb}
bleibt: \verb-\TeX- Text. |Normaler Text A. Normaler Text A.
Normaler Text B. \CommentMarkerB|Das bleibt nicht. |Normaler
Text B. Normaler Text B. \CommentMarkerB|Das bleibt nicht und
der naechste Absatz auch nicht:
Hier ist der naechste Absatz. |Normaler Text B. Normaler Text B.
\bigskip
Hier ein Beispiel mit geschweifte-Klammern-Syntax:
Normaler Text A. \CommentMarkerA{Das {}{bleibt}. Das
bleibt. }Normaler Text A. Normaler Text A. \CommentMarkerA{Das bleibt.
Und der naechste Absatz auch:
Hier ist der naechste Absatz. Auch \texttt{\string\verb}
bleibt: \verb-\TeX- Text. }Normaler Text A. Normaler Text A.
Normaler Text B. \CommentMarkerB{Das bleibt nicht. }Normaler
Text B. Normaler Text B. \CommentMarkerB{Das bleibt nicht und
der naechste Absatz auch nicht:
Hier ist der naechste Absatz. }Normaler Text B. Normaler Text B.
\bigskip
Hier was mit und ohne Mais und mit und ohne Gurken:
\MyIncludeCommentmarkerCommand{\Mais}
\MyIncludeCommentmarkerCommand{\Gurken}
\MyExcludeCommentmarkerCommand{\MaisOderGurken}
\Mais{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
\Gurken{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
Dies ist ein Satz%
\MaisOderGurken{, der von }\Mais{gelbem Mais }\Mais{\Gurken{und
von }}\Gurken{gruenen Gurken }\MaisOderGurken{handelt}.
\MyIncludeCommentmarkerCommand{\Mais}
\MyExcludeCommentmarkerCommand{\Gurken}
\MyExcludeCommentmarkerCommand{\MaisOderGurken}
\Mais{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
\Gurken{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
Dies ist ein Satz%
\MaisOderGurken{, der von }\Mais{gelbem Mais }\Mais{\Gurken{und
von }}\Gurken{gruenen Gurken }\MaisOderGurken{handelt}.
\MyExcludeCommentmarkerCommand{\Mais}
\MyIncludeCommentmarkerCommand{\Gurken}
\MyExcludeCommentmarkerCommand{\MaisOderGurken}
\Mais{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
\Gurken{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
Dies ist ein Satz%
\MaisOderGurken{, der von }\Mais{gelbem Mais }\Mais{\Gurken{und
von }}\Gurken{gruenen Gurken }\MaisOderGurken{handelt}.
\MyExcludeCommentmarkerCommand{\Mais}
\MyExcludeCommentmarkerCommand{\Gurken}
\MyExcludeCommentmarkerCommand{\MaisOderGurken}
\Mais{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
\Gurken{\MyIncludeCommentmarkerCommand{\MaisOderGurken}}
Dies ist ein Satz%
\MaisOderGurken{, der von }\Mais{gelbem Mais }\Mais{\Gurken{und
von }}\Gurken{gruenen Gurken }\MaisOderGurken{handelt}.
\end{document}
Ulrich