provideenvironment analog zu providecommand?

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:

provideenvironment analog zu providecommand?

Beitrag von iTob »

Guten Abend,

grade für Paketautoren, kann es ja sinnvoll sein, statt \newcommand \providecommand zu verwenden, weil dieser ein Makro nur definiert, wenn es nicht bereits existiert (richtig?). Daher meine Frage:

Gibt es einen analogen Befehl, mit dem man Umgebungen definieren kann?

Zwei Alternativen, die mir bereits eigefallen sind, von den ich aber auch nicht sicher bin, ob die gehen:
  1. Mit dem Code
    \@ifundefined{\beginmyenv}{%
        % Definition durchführen
    }{%
        % nix machen
    }
    prüfen, ob die Umgebung bereits definiert ist und wenn nicht, diese erstellen.
  2. Statt mit \newenvironment zur arbeiten könnte man doch auch direkt die makros \beginmyenc und \endmyenv definieren mit \providecommand oder? AFU was müsste man dabei achten?
Danke und viele Grüße!
Tobi

Benutzeravatar
KOMA
TeX-Entwickler
TeX-Entwickler
Beiträge: 2958
Registriert: Fr 4. Jul 2008, 17:28
Kontaktdaten:

Beitrag von KOMA »

Eine Umgebung foo ist über die Makros \foo und \endfoo definiert, wobei \endfoo auch undefiniert sein kann. Man kann mit den Anweisungen \newcommand und \providecommand keine Makros \end... definieren. Die Lösung würde also lauten:
\@ifundefined{foo}{%
  \newenvironment{foo}{...}{...}%
}{%
}
Natürlich kann man sich daraus auch wieder einen Befehl definieren (ungetestet):
\providecommand*{\provideenvironment}[1]{%
  \@ifundefined{#1}{\newenvironment{#1}}{\@gobbletwo}%
}
ABER: Hier fehlt noch eine Behandlung für die Stern-Version \provideenvironment* analog zu \providecommand*.

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

Beitrag von iTob »

Gutem Morgen,

alles klar, da es (bisher) nur um eine Umgebung geht, wird deine erste Version wohl reichen. Danke!

Tobi

pospiech
Moderator
Moderator
Beiträge: 247
Registriert: Do 3. Jul 2008, 11:40
Wohnort: Hannover
Kontaktdaten:

Beitrag von pospiech »

KOMA hat geschrieben:ABER: Hier fehlt noch eine Behandlung für die Stern-Version \provideenvironment* analog zu \providecommand*.
Aber wie erstellt man denn die * Version dazu?

Ich würde den Code gerne bei mir in ein Paket einpacken.

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

Beitrag von iTob »

Meinst du, wie man grundsätzlich Sternversionen erstellt oder wie die analoge Sternversion in diesem Fall aussehen müsste?
Für erstes kann ich die hierauf verweisen …
Wenn du was zu letzterem suchst, kann ich leider nicht helfen.

Grüße,
Tobi

pospiech
Moderator
Moderator
Beiträge: 247
Registriert: Do 3. Jul 2008, 11:40
Wohnort: Hannover
Kontaktdaten:

Beitrag von pospiech »

Da steht im wesentlichen wie man es unschön lösen kann und wie mit dem suffix Paket:
\WithSuffix\gdef\mycommand*{starred version}
ob das genauso für Umgebungen gilt muss ich noch testen.

Nerd 032F

Beitrag von Nerd 032F »

\newcommand*{\provideenvironment}{%
  \@ifstar {\@sprovideenvironment}{\@provideenvironment}%
}
\newcommand*{\@sprovideenvironment}[1]{%
  \@ifundefined{#1}{\newenvironment*{#1}}{\@gobbletwo}%
}
\newcommand*{\@provideenvironment}[1]{%
  \@ifundefined{#1}{\newenvironment{#1}}{\@gobbletwo}%
}

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

Beitrag von iTob »

pospiech hat geschrieben:Da steht im wesentlichen wie man es unschön lösen kann …
Warum was ist gegen die ifstar-Varaiante zu sagen?

Benutzeravatar
KOMA
TeX-Entwickler
TeX-Entwickler
Beiträge: 2958
Registriert: Fr 4. Jul 2008, 17:28
Kontaktdaten:

Beitrag von KOMA »

Nerd 032F hat geschrieben:
\newcommand*{\provideenvironment}{%
  \@ifstar {\@sprovideenvironment}{\@provideenvironment}%
}
\newcommand*{\@sprovideenvironment}[1]{%
  \@ifundefined{#1}{\newenvironment*{#1}}{\@gobbletwo}%
}
\newcommand*{\@provideenvironment}[1]{%
  \@ifundefined{#1}{\newenvironment{#1}}{\@gobbletwo}%
}
Das alleine nützt noch gar nichts. Hier werden nämlich die Argumente noch gar nicht berücksichtigt. Damit bringt auch die Sternvariante nichts. Ein \provideenvironment müsste ja folgende Möglichkeiten berücksichtigen:
  1. \provideenvironment{NAME}{BEGIN}{END}
  2. \provideenvironment*{NAME]{BEGIN}{END}
  3. \provideenvironment{NAME}[1-9]{BEGIN}{END}
  4. \provideenvironment*{NAME}[1-9]{BEGIN}{END}
  5. \provideenvironment{NAME}[1-9][DEFAULT]{BEGIN}{END}
  6. \provideenvironment*{NAME}[1-9][DEFAULT]{BEGIN}{END}
Obige Lösung berücksichtigt aber nur die Möglichkeiten 1 und 2. Die übrigen Möglichkeiten werden von \@gobbletwo nicht korrekt behandelt. Man benötigt also eigentlich ein \@gobbletwooptionalandtwomandatory:
\newcommand*{\@gobbletwooptionalandtwomandatory}[1][]{%
  \@gobbleoneoptionalandtwomandatory}
\newcommand*{\@gobbleoneoptionalandtwomandatory}[3][]{}
Ausprobiert habe ich das nicht. Besser wäre eventuell, wenn man stattdessen den Trick, den LaTeX bei \providecommand auf \provideenvironment überträgt:
\def\provideenvironment{\@star@or@long\provide@environment}
\def\provide@environment#1{%
  \@ifundefined{#1}{%
    {\def\reserved@a{\new@environment{#1}}%
    {\def\reserved@a{\renew@environment{reserved@a}}%
  \reserved@a}%
Dabei wird also im Falle, dass die Umgebung bereits definiert ist, einfach die Umgebung reserved@a umdefiniert, also \reserved@a und \endreserved@a. Dass dabei die Anweisung \endreserved@a neu definiert wird, sollte kein Problem sein. Ich denke nicht, dass irgend jemand diese Anweisung für etwas sinnvolles verwendet. Wenn man Befürchtungen hat, kann man sich zuvor (also außerdem der Definition von \provide@environment) mit
\@ifundefined{endreserved@a}{}{\@latex@error{%
  Command \@backslashchar endreserved@a already defined}\@eha
}
absichern.

Wie gesagt, das ist ungetestet. Falls es nicht funktioniert, wäre ein Testdokument praktisch.

PS: Letztlich ist das auch nur die \@ifstar-Variante. Da hier aber das Verhalten identisch zu dem der entsprechenden LaTeX-Befehle ist, halte ich das für die durchaus gewollte Lösung.

Antworten