Makro mit Asterix zwischen den Argumenten Thema ist als GELÖST markiert

Redefinition von Makros, Definition eigener Befehle sowie neuer Umgebungen


Theodor86

Makro mit Asterix zwischen den Argumenten

Beitrag von Theodor86 »

Guten Abend!
Die, die das AMSRef Package kennen, kennen auch folgenden Befehl:
 \cite{123}*{ABC} 
Das Ergebnis liefert dann (123,ABC) - mit eckigen Klammern natürlich..

Ich wollte gerne diese Fähigkeit kombinieren, und zwar für:
\eqref{ABC}, \eqref[123]{ABC}, \eqref{ABC}*{123}
und dem Ergebnis (ABC), (ABC,123) und (ABC,123).

Ich habe dafür die Codes von amsref.sty und rkeyval.sty quergelesen und folgenden Code geschrieben:
 \makeatletter
 \def\@ifEmpty#1{\def\@temp{#1}\ifx\@temp\@empty}
 \let\original@eqref\eqref
 \def\asterix@#1{\def\asterix@a##1{#1}\def\asterix@b{#1{}}\futurelet\vergleich@token\asterix@test}
 \def\asterix@test{\ifx{*}\vergleich@token{\let\asterix@b\asterix@a}\fi\asterix@b}
 \def\print@eqref#1#2{\@ifEmpty{#2}\original@eqref{#1}\else{(\ref{#1},#2)}\fi}
 \renewcommand{\eqref}[2][]{\@ifEmpty{#1}\asterix@{\print@eqref{#2}}\else\print@eqref{#2}{#1}\fi} 
 \makeatother
Im Prinzip ist das eine 1:1 Kopie des \star@ Makros aus rkeyval.sty. Der Code wird auch wunderbar kompiliert. Allerdings erkennt er partout nicht das Asterix * wenn ich
\eqref{ABC}*{123}
benutze. Es erscheint dann (ABC)*123 in der Ausgabe.

Über die eine oder andere Idee würde ich mich sehr freuen :)
Danke!

Benutzeravatar
cgnieder
Forum-Meister
Forum-Meister
Beiträge: 730
Registriert: Fr 22. Okt 2010, 18:37
Wohnort: Herrenberg
Kontaktdaten:

Beitrag von cgnieder »

Hallo,

Erst einmal: +1 für den Asterix!

Etwas übersichtlicher sieht Dein Code so aus:
\makeatletter
 \def\@ifEmpty#1{%
   \def\@temp{#1}%
   \ifx\@temp\@empty}
 
 \let\original@eqref\eqref
 
 \def\asterix@#1{%
   \def\asterix@a##1{#1}%
   \def\asterix@b{#1{}}%
   \futurelet\vergleich@token\asterix@test}
 
 \def\asterix@test{%
   \ifx{*}\vergleich@token
     {\let\asterix@b\asterix@a}%
   \fi
   \asterix@b}
 
 \def\print@eqref#1#2{%
   \@ifEmpty{#2}
     \original@eqref{#1}%
   \else
     {(\ref{#1},#2)}%
   \fi}
 
 \renewcommand*\eqref[2][]{%
   \@ifEmpty{#1}%
     \asterix@{\print@eqref{#2}}%
   \else
     \print@eqref{#2}{#1}%
   \fi}
 \makeatother
Der Code macht an zwei Stellen Probleme. Erstens \asterix@test:
\def\asterix@test{%
   % der Test kann direkt mit dem Stern erfolgen:
   \ifx{*}\vergleich@token
     % das folgende muss aus der Gruppe, sonst ist später \asterix@b unbekannt
     {\let\asterix@b\asterix@a}%
   \fi
   \asterix@b}
Neu:
 \def\asterix@test{%
   \ifx*\vergleich@token
     \let\asterix@b\asterix@a%
   \fi
   \asterix@b}
Zweitens: die Neudefinition von \eqref:
\renewcommand*\eqref[2][]{%
   \@ifEmpty{#1}%
     % durch \asterix@ wird \vergleich@token=\else und nie zum *
     \asterix@{\print@eqref{#2}}%
   \else
     \print@eqref{#2}{#1}%
   \fi}
Neu:
\renewcommand*\eqref[2][]{%
   \@ifEmpty{#1}%
     \expandafter\@firstoftwo
   \else
     \expandafter\@secondoftwo
   \fi
   {\asterix@{\print@eqref{#2}}}%
   {\print@eqref{#2}{#1}}
dann sieht's komplett so aus:
\documentclass{article}
\usepackage{amsmath}
\makeatletter
 \def\@ifEmpty#1{%
   \def\@temp{#1}%
   \ifx\@temp\@empty}
 
 \let\original@eqref\eqref
 
 \def\asterix@#1{%
   \def\asterix@a##1{#1}%
   \def\asterix@b{#1{}}%
   \futurelet\vergleich@token\asterix@test}
 
 \def\asterix@test{%
   \ifx*\vergleich@token
     \let\asterix@b\asterix@a%
   \fi\asterix@b}
 
 \def\print@eqref#1#2{%
   \@ifEmpty{#2}
     \original@eqref{#1}%
   \else
     {(\ref{#1},#2)}%
   \fi}
 \renewcommand*\eqref[2][]{%
   \@ifEmpty{#1}%
     \expandafter\@firstoftwo
   \else
     \expandafter\@secondoftwo
   \fi
   {\asterix@{\print@eqref{#2}}}%
   {\print@eqref{#2}{#1}}}
 \makeatother 
\begin{document}
\begin{equation}
 1 + 2 \label{eq:a}
\end{equation}
\eqref{eq:a} \eqref[blub]{eq:a} \eqref{eq:a}*{bla}
\end{document}
Gruß
Clemens
Paketauthor

Theodor86

Danke!

Beitrag von Theodor86 »

Hallo Clemens!

Erst einmal vielen, vielen Dank für deine unheimlich schnelle und super kompetente Antwort! Damit hätte ich nicht gerechnet! Und deswegen wollte ich meinen Dank etwas länger ausschreiben.

1.) Asterisk, nicht Asterix.... ich mache den Fehler seit der dritten Klasse durchgehend... aber ist ja wenigstens ein süßer Fehler ^^

2.) Ich weiß, dass und wie man Code übersichtlicher schreibt. Aber da ich den Fehler nicht fand, dachte ich schon, es läge an einem falsch gesetzten %... was natürlich total falsch war. ^^

3.) Das irgendwo in \asterix@test ein Fehler war, wusste ich auch schon, wollte aber erst den anderen finden, bevor ich mich darum kümmerte. Vielen Dank, dass du dich auch darum bemüht hast :) Finde ich toll!

4.) Und nun zum wichtigsten Punkt. Gut, ich bin ein totaler Neuling was Programmieren in Tex angeht (schreiben tu ich in Tex schon ein paar Jahre). Und ich wäre nie darauf gekommen, dass beim Expandieren des Macros sich \futurelet das \else schnappt. Das muss man ja erst einmal wissen! Erklärt aber auch, warum \vergleich@token immer "leer" war. Ich habe mir \vergleich@token ausgeben lassen, aber im PDF war die Stelle dann immer leer - jetzt ist auch klar warum.

Also, vielen, vielen Dank für die Hilfe! Ohne dich hätte ich es nicht geschafft, und Google hat dazu natürlich nichts ausgeben (nach \foo{}*{} kann man schlecht googeln). Es läuft jetzt alles genauso, wie ich es wollte. Also, super von dir!

Mechanicus
Forum-Guru
Forum-Guru
Beiträge: 322
Registriert: Mi 8. Okt 2008, 18:41
Wohnort: Hamburg

Beitrag von Mechanicus »

Hi,

hier ein Vorschlag mit xparse. Natürlich ausbaufähig :D
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\cs_set_eq:NN \theodor_save_eqref:n \eqref

\DeclareDocumentCommand \eqref { o m  s g }
 {
  \IfNoValueTF { #1 }
      {%kein erstes optionales Argument 
         \IfBooleanTF { #3 } 
            { % Sternversion
               { ( \ref {#2} , #4 ) }
            }
            { %kein Stern
               \theodor_save_eqref:n { #2 }
             }     
       }
      { %erstes optionales Argument vorhanden
         %kein Text auf ASTERIX ;-) + zweites Argument
          { ( \ref {#2} , #1 ) }
      }
 }
\ExplSyntaxOff

\begin{document}
\begin{equation}
 1 + 2 \label{eq:a}
\end{equation}

\verb+\eqref{eq:a}+\qquad\eqref{eq:a} 

\verb+\eqref[blub]{eq:a}+\qquad\eqref[blub]{eq:a}

\verb+\eqref{eq:a}*{bla}+\qquad\eqref{eq:a}*{bla}
\end{document}
Marco
Personalführung ist die Kunst der Vorgesetzten den Untergebenen so schnell über den Tisch zu ziehen, dass er die Reibungshitze als Nestwärme empfindet.

Theodor86

Beitrag von Theodor86 »

Hallo Marco!
Vielen Dank für den Hinweis auf das 'xparse' Paket. In der Tat hatte ich im Anfang nach so etwas gesucht und nicht gefunden und dann erst entschieden, es selber zu Fuß zu machen. Das Paket kommt auf jeden Fall auf meine 'Merkliste', falls noch einmal so ein Fall eintritt - immerhin sind noch komplexere Konstruktionen damit möglich!
Vielen Dank!

Benutzeravatar
cgnieder
Forum-Meister
Forum-Meister
Beiträge: 730
Registriert: Fr 22. Okt 2010, 18:37
Wohnort: Herrenberg
Kontaktdaten:

Re: Danke!

Beitrag von cgnieder »

Theodor86 hat geschrieben:3.) Das irgendwo in \asterix@test ein Fehler war, wusste ich auch schon, wollte aber erst den anderen finden, bevor ich mich darum kümmerte. Vielen Dank, dass du dich auch darum bemüht hast :) Finde ich toll!
Für mich waren alle Befehle Teil eines ganzen. Der eine Fix hätte ohne den anderen nicht funktionert... :)

@Marco: witzig -- ich hatte zuerst fast genau dasselbe :) , bis ich mich entschlossen habe, doch mal nach den eigentlichen Fehlern zu suchen.

@Theodor Wieso eigentlich nicht eine leichtere und IMHO intuitivere Syntax wie z.B. so:
\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand\eqref{omo}
  {(\IfNoValueF{#1}{#1,~}\ref{#2}\IfNoValueF{#3}{,~#3})}

\begin{document}
\begin{equation}
 1 + 1 \neq 3 \label{eq:a}
\end{equation}

\eqref{eq:a} oder \eqref[bla]{eq:a} oder \eqref{eq:a}[blub] oder \eqref[bla]{eq:a}[blub]

\end{document}
Gruß
Clemens
Paketauthor

Mechanicus
Forum-Guru
Forum-Guru
Beiträge: 322
Registriert: Mi 8. Okt 2008, 18:41
Wohnort: Hamburg

Re: Danke!

Beitrag von Mechanicus »

cgnieder hat geschrieben:@Marco: witzig -- ich hatte zuerst fast genau dasselbe :) , bis ich mich entschlossen habe, doch mal nach den eigentlichen Fehlern zu suchen.
Warum mit Altlasten rumschlagen :)
Personalführung ist die Kunst der Vorgesetzten den Untergebenen so schnell über den Tisch zu ziehen, dass er die Reibungshitze als Nestwärme empfindet.

Theodor86

Beitrag von Theodor86 »

@Marco: Damit ich diesen \futurelet Befehl einfach mal verstehe ^^
@Clemens: Auch sehr nett und von seiner Schlankheit wohl nicht zu unterbieten.

Antworten