Seite 1 von 1

Makro mit Asterix zwischen den Argumenten

Verfasst: Sa 16. Jun 2012, 02:26
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!

Verfasst: Sa 16. Jun 2012, 19:16
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ß

Danke!

Verfasst: So 17. Jun 2012, 03:07
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!

Verfasst: So 17. Jun 2012, 12:42
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

Verfasst: So 17. Jun 2012, 14:10
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!

Re: Danke!

Verfasst: So 17. Jun 2012, 16:40
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ß

Re: Danke!

Verfasst: So 17. Jun 2012, 17:26
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 :)

Verfasst: So 17. Jun 2012, 18:39
von Theodor86
@Marco: Damit ich diesen \futurelet Befehl einfach mal verstehe ^^
@Clemens: Auch sehr nett und von seiner Schlankheit wohl nicht zu unterbieten.