\@ifstar innerhalb von \if..\else..\fi

Redefinition von Makros, Definition eigener Befehle sowie neuer Umgebungen


Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

\@ifstar innerhalb von \if..\else..\fi

Beitrag von iTob »

Hallo,

ich habe ein kleines Problem mit dem \@ifstar-Befehl. Wenn ich ihn »normal« benutze, geht alles, aber wenn ich den Befehl innerhalb einer \if-Struktur verwenden will, geht es nicht.
Hintergrund: Ich würde gerne durch eine Paketoption, die mir als \if@<paketoption> die Stern- und normale Definition eines Makros vertauschen können.

Hier mal ein Beispiel, in dem ich die \if-Anweisung einfach so definiere, da das Problem vermutlich nicht im Paket sondern meiner Verwendung von \@ifstar liegt. Ich hab auch schon zwei Verschiedene Varianten probiert, die beide nicht gehen...
\documentclass[fontsize=10pt, DIV=11,a4paper]{scrartcl}
\usepackage[latin1]{inputenc}

\makeatletter
	
	% die Paketoption wird hier schlicht als if defniniert
	\newif\if@paketoption
	\@paketoptiontrue
%	\@paketoptionfalse
	
	% die beiden Befhele, die durch Stern unterschieden werden sollen
	\providecommand{\@testnorm}{\textbf{ohne} Stern}
	\providecommand{\@teststar}{\textbf{mit} Stern}
	
	% ein "normaler" Aufruf von \@ifstar geht
	\providecommand{\klapptimmer}{%
		\@ifstar \@teststar \@testnorm%
	}
	
	% und zwei Versuche, das ganze mit einer if-Abfrage
	% bei Bedarf vertauschen zu können
	\providecommand{\versucheins}{%
		\if@paketoption
			\@ifstar \@notestar \@notenorm
		\else
			\@ifstar{\@notenorm}{\@notestar}
		\fi
	}
	\providecommand{\versuchzwei}{%
		\@ifstar%
			{\if@paketoption\@notestar\else\@notenorm\fi}%
			{\if@paketoption\@notenorm\else\@notestar\fi}
	}


\makeatother

\begin{document}
\section*{\texttt{@ifstar}-Problem}
Zuerst die Version, die immer geht:

An dieser Stelle der gesternte Aufruf: \klapptimmer* (Soll: \textit{mit Stern})

An dieser Stelle der normale Aufruf: \klapptimmer\ (Soll: \textit{ohne Stern})

\bigskip
\noindent Jetzt der missglueckte Versuch 1:

gesternter Aufruf: \versucheins* (Soll: \textit{mit Stern}, wenn \texttt{@paketoption=true}, sonst \textit{ohne Stern})

gesternter Aufruf: \versucheins (Soll: \textit{ohne Stern}, wenn \texttt{@paketoption=true}, sonst \textit{nit Stern})

\bigskip
\noindent Und der zweite missglueckte Versuch:

gesternter Aufruf: \versuchzwei* (Soll: \textit{mit Stern}, wenn \texttt{@paketoption=true}, sonst \textit{ohne Stern})

gesternter Aufruf: \versuchzwei (Soll: \textit{ohne Stern}, wenn \texttt{@paketoption=true}, sonst \textit{nit Stern})

\end{document}
Vielen Dank für Eure Hilfe!
Grüße, Tobi
Zuletzt geändert von iTob am Sa 11. Sep 2010, 17:22, insgesamt 1-mal geändert.

sommerfee
Forum-Century
Forum-Century
Beiträge: 219
Registriert: Sa 12. Jul 2008, 08:02

Beitrag von sommerfee »

Das hängt damit zusammen, wann TeX was expandiert. Das \@ifstar geht schief, weil da quasi ein \else bzw. \fi im Weg liegt.

Man kann das entweder durch die obligatorischen \expandafter-Orgien versuchen zu lösen, oder aber durch ein Hilfsmakro. Letzteres mag weniger sportlich sein, finde ich aber besser nachvollziehbar:
   \providecommand{\versucheins}{%
      \if@paketoption 
         \def\next{\@ifstar \@teststar \@testnorm}%
      \else 
         \def\next{\@ifstar \@testnorm \@teststar}%
      \fi
      \next
   } 
Alternativ könnte man auch die Verschachtelung von \if@paketoption und \@ifstar umdrehen:
   \providecommand{\versucheins}{%
      \@ifstar
        {\if@paketoption\@teststar\else\@testnorm\fi}%
        {\if@paketoption\@testnorm\else\@teststar\fi}%
   } 
Zum zweiten Lösungsansatz kann ich nichts sagen, da die Definition von \if@numberedsrcnotes fehlt.

Liebe Grüße,
Axel

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

sommerfee hat geschrieben: Zum zweiten Lösungsansatz kann ich nichts sagen, da die Definition von \if@numberedsrcnotes fehlt.
Danke, werde deinen Vorschlag nachher gleich testen. Der zweite VErsuch war genau das vertauschen der Schachtelung, ich hab nur vergessen aus numberedsrcnotes paketoption zu machen. :oops:

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

Sehr gut, dein Vorschlag mit dem Hilfsmakro funktioniert, auch wenn es einen Moment gedauert hat, bis ich begriffen hatte, dass \next kein LaTeX-Primitiv oder so ist...

Danke nochmal!!

sommerfee
Forum-Century
Forum-Century
Beiträge: 219
Registriert: Sa 12. Jul 2008, 08:02

Beitrag von sommerfee »

iTob hat geschrieben:Der zweite VErsuch war genau das vertauschen der Schachtelung, ich hab nur vergessen aus numberedsrcnotes paketoption zu machen. :oops:
Dann sollte der aber funktionieren, und mir persönlich gefällt er auch besser als der erste Lösungsansatz.

Vielleicht magst du dein Beispiel aus Beitrag #1 so editieren, daß man es auch ohne Veränderungen (\@notestar statt \@teststar etc.) übersetzen kann?

Liebe Grüße,
Axel

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

Hallo,

ja ich hätte die Lösung ohne Hilfsmakro auch besser gefunden und hab hier nochmal ein neues Beispiel dazu:
\documentclass[11pt,a4paper]{scrartcl}
\usepackage[latin1]{inputenc}

\makeatletter

	\newif\if@numberedsrcnotes
	\@numberedsrcnotestrue
	
	\newcommand{\@notenorm}[1]{%
		\textbf{ohne Stern}%
	}%
	
	\newcommand{\@notestar}[1]{%
		\textbf{mit Stern}%
	}%
	
	\providecommand{\note}{%
		\@ifstar%
			{\if@numberedsrcnotes\@notestar\else\@notenorm\fi}
			{\if@numberedsrcnotes\@notenorm\else\@notestar\fi}
	}%
	
	\newcommand{\option}{\if@numberedsrcnotes true \else false \fi}

\makeatother

\begin{document}
	Option: \texttt{@numberedsrcnotestrue = \option}
	
	\bigskip
	gesternter Aufruf: (Ist:) \note*
	
	(Soll: \textbf{mit Stern}, wenn
	\texttt{@numberedsrcnotestrue=true}, sonst \textbf{ohne Stern})
	
	\bigskip
	normaler Aufruf: (Ist:) \note
	
	(Soll: \textbf{ohne Stern}, wenn
	\texttt{@numberedsrcnotestrue=true}, sonst \textbf{mit Stern})
\end{document}
Das Beispiel lässt sich kompilieren, aber nur, wenn die Option false ist, erscheint der Richtige Text. Bei true werden offensichtlich beide \if@numberedsrcnotestrue in der \note-Definition ausgeführt.
Der Versuch den \if@star-befehl durch einfügen von \else und \fi besser zu strukturieren ist gescheitert...

Viele Grüße
Tobi

sommerfee
Forum-Century
Forum-Century
Beiträge: 219
Registriert: Sa 12. Jul 2008, 08:02

Beitrag von sommerfee »

Das liegt an der Definition von \@notestar und \@notenorm, die "klauen" das jeweils nächste Token als Argument, weil sie als Makros mit Argument definiert sind.

So hingegen sollte es klappen:
 \newcommand{\@notenorm}{% 
      \textbf{ohne Stern}% 
   }% 
    
   \newcommand{\@notestar}{% 
      \textbf{mit Stern}% 
   }%
Liebe Grüße,
Axel

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

Nabend Alex,

die sollten ja Argumente haben, ich hab dann nur vergessen, die mit anzugeben.

Hier das lauffähige Beispiel mit Argumenten:
\documentclass[11pt,a4paper]{scrartcl}
\usepackage[latin1]{inputenc}

\makeatletter

	\newif\if@numberedsrcnotes
%	\@numberedsrcnotestrue
	
	\newcommand{\@notenorm}[1]{%
		\textbf{ohne Stern} Argument: #1%
	}%
	
	\newcommand{\@notestar}[1]{%
		\textbf{mit Stern} Argument: #1%
	}%
	
	\providecommand{\note}{%
		\@ifstar%
			{\if@numberedsrcnotes\@notestar\else\@notenorm\fi}
			{\if@numberedsrcnotes\@notenorm\else\@notestar\fi}
	}%
	
	\newcommand{\option}{\if@numberedsrcnotes true \else false \fi}

\makeatother

\begin{document}
	Option: \texttt{@numberedsrcnotestrue = \option}
	
	\bigskip
	gesternter Aufruf: (Ist:) \note*{Test}
	
	(Soll: \textbf{mit Stern}, wenn
	\texttt{@numberedsrcnotestrue=true}, sonst \textbf{ohne Stern})
	
	\bigskip
	normaler Aufruf: (Ist:) \note{Test}
	
	(Soll: \textbf{ohne Stern}, wenn
	\texttt{@numberedsrcnotestrue=true}, sonst \textbf{mit Stern})
\end{document}
ABER: Wenn ich in meinem Paket das (= die andere Lösung, die aber gut funktioniert)
	\renewcommand{\note}{% usercommand for notes, numbered, *= unnumbered
		\if@numberedsrcnotes 
			\def\@note{\@ifstar \@notestar \@notenorm}% 
		\else 
			\def\@note{\@ifstar \@notenorm \@notestar}% 
		\fi 
		\@note
	}%
durch den neuen Code für die \note-Definition (auch mit \renewcommand, statt \providecommand) bekomme ich den folgenden Fehler:
! Missing } inserted
und das gleich mehrfach. Kommentiere ich die neue Definition wieder aus und die alte ein, verschwinden alle Fehler und es läuft problemlos... komisch...

sommerfee
Forum-Century
Forum-Century
Beiträge: 219
Registriert: Sa 12. Jul 2008, 08:02

Beitrag von sommerfee »

iTob hat geschrieben: ABER: Wenn ich in meinem Paket das (= die andere Lösung, die aber gut funktioniert)
durch den neuen Code für die \note-Definition (auch mit \renewcommand, statt \providecommand) bekomme ich den folgenden Fehler:
! Missing } inserted
und das gleich mehrfach. Kommentiere ich die neue Definition wieder aus und die alte ein, verschwinden alle Fehler und es läuft problemlos... komisch...
Das kann ich nicht nachvollziehen. Dein Beispiel läuft bei mir, und wenn ich die andere Definition einbaue, ebenfalls. Da muß dir irgendein anderer dummer Fehler beim Ersetzen der Definition unterlaufen sein...
\documentclass[11pt,a4paper]{scrartcl} 
\usepackage[latin1]{inputenc} 

\makeatletter 

   \newif\if@numberedsrcnotes 
   \@numberedsrcnotestrue 
    
   \newcommand{\@notenorm}[1]{% 
      \textbf{ohne Stern} Argument: #1% 
   }% 
    
   \newcommand{\@notestar}[1]{% 
      \textbf{mit Stern} Argument: #1% 
   }% 
    
   \providecommand{\note}{% 
      \@ifstar% 
         {\if@numberedsrcnotes\@notestar\else\@notenorm\fi} 
         {\if@numberedsrcnotes\@notenorm\else\@notestar\fi} 
   }% 
    
   \renewcommand{\note}{% usercommand for notes, numbered, *= unnumbered 
      \if@numberedsrcnotes 
         \def\@note{\@ifstar \@notestar \@notenorm}% 
      \else 
         \def\@note{\@ifstar \@notenorm \@notestar}% 
      \fi 
      \@note 
   }%

   \newcommand{\option}{\if@numberedsrcnotes true \else false \fi} 

\makeatother 

\begin{document} 
   Option: \texttt{@numberedsrcnotestrue = \option} 
    
   \bigskip 
   gesternter Aufruf: (Ist:) \note*{Test} 
    
   (Soll: \textbf{mit Stern}, wenn 
   \texttt{@numberedsrcnotestrue=true}, sonst \textbf{ohne Stern}) 
    
   \bigskip 
   normaler Aufruf: (Ist:) \note{Test} 
    
   (Soll: \textbf{ohne Stern}, wenn 
   \texttt{@numberedsrcnotestrue=true}, sonst \textbf{mit Stern}) 
\end{document}
Liebe Grüße,
Axel

Benutzeravatar
iTob
Forum-Meister
Forum-Meister
Beiträge: 1221
Registriert: Mo 19. Apr 2010, 22:19
Kontaktdaten:

Beitrag von iTob »

Ja, sehr komisch... werde bei Gelegenheit noch mal danach sehen und mich dann wieder melden,

erst mal vielen Dank und
gute Nacht!

Antworten