Umgebung die den Code innerhalb verschluckt

Redefinition von Makros, Definition eigener Befehle sowie neuer Umgebungen


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

Umgebung die den Code innerhalb verschluckt

Beitrag von pospiech »

Ich möchte ganze Abschnitte in der Präambel ein und ausschalten können:
\begin{TemplatePdfSection}
\usepackage{...}
....
\end{TemplatePdfSection}
und dachte dabei an diese Befehle
\DefineTemplateSection[enabled]{TemplatePdfSection}
% zusammen mit 
\SetTemplateSection{TemplatePdfSection}{enabled}
die wesentliche Frage ist - wie erzeuge ich eine Umgebung die den Inhalt komplett wegwirft, oder überhaupt nicht beeinflusst?

Probiert habe ich es mit folgendem Code, aber der wirft mir sofort Fehler sobald ich Code in eine Umgebung packe. Das Paket comment ist auch nicht meine erste Wahl, aber das einzige was ich dafür kannte um es zu missbrauchen...
\documentclass[]{article}

%\usepackage[latin1]{inputenc}
%\input{preambel/preambel}

\RequirePackage{ifthen}
\makeatletter
%%% --- basic missing latex code 
\newcommand*{\provideenvironment}{%
  \@ifstar {\@sprovideenvironment}{\@provideenvironment}%
}
\newcommand*{\@sprovideenvironment}[1]{%
  \@ifundefined{#1}{\newenvironment*{#1}}{\@gobbletwo}%
}
\newcommand*{\@provideenvironment}[1]{%
  \@ifundefined{#1}{\newenvironment{#1}}{\@gobbletwo}%
}
\makeatother

\RequirePackage{comment}

% \DefineTemplateSection[enabled]{TemplatePdfSection}
\newcommand{\DefineTemplateSection}[2][true]{ %
	% create environment that does nothing
	\provideenvironment*{#2}{}{}
	% check how to handle the contents
	\ifthenelse{\boolean{#1}}{
		% do nothing 		
	}{
		% hide contents of environment
		\excludecomment{#2}
	}
}%


\DefineTemplateSection[false]{TemplateMath}
\DefineTemplateSection[true]{TemplateFigures}

% \newenvironment{TemplateMath}{}{}
% \newenvironment{TemplateFigures}{}{}

\begin{TemplateMath}
\usepackage{amsmath}
\end{TemplateMath}
%
\begin{TemplateFigures}
\usepackage{graphicx}
\end{TemplateFigures}

\listfiles

\begin{document}
\end{document}


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

Beitrag von KOMA »

Dein Hauptproblem ist, dass eine normale Umgebung - und dazu gehört auch eine mit \provideenvironment (Deine Version davon funktioniert übrigens nicht wie \newenvironment o. ä.) definierte - immer eine Gruppe einfügt. Ein Paket in einer Gruppe zu laden ist aber .. naja, ich muss das sicher nicht weiter ausführen.

comment bietet aber bereits alles, was Du brauchst.
\newcommand{\DefineTemplateSection}[2][true]{%
  % check how to handle the contents
  \ifthenelse{\boolean{#1}}{%
    \includecomment{#2}%
  }{%
    % hide contents of environment
    \excludecomment{#2}%
  }%
}%
Ansonsten würde natürlich für Deinen Zweck auch etwas wie \newif genügen:
\newif\ifVariantSectionMathe\ifVariantSectionMathefalse
...
\ifVariantSectionMathe
\usepackage{amsmath}
\fi

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

Beitrag von pospiech »

D.h. wenn ich das über einen normalen Befehl mache würde es funktionieren, aber bei einer Umgebung(Gruppe) nicht?

Das ist insofern schade, weil man das Ende der Umgebung, als der schließenden Klammer des Befehls leicht übersieht.

Dein \DefineTemplateSection würde wenn ich das richtig verstehe so funktionieren:
\DefineTemplateSection{true}
{
    \usepackage{...}
}
Ich müsste das dann so umbasteln das es eher so lauten würde
\IfUseInTemplate[true]{math}
{
    \usepackage{...}
}

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

Beitrag von KOMA »

Mein \DefineTemplateSection mit \includecomment funktioniert genau so, wie Du Dir das AFAIK für Deine Version gewünscht hast, weil nämlich mit comment definierte Umgebungen keine normalen Umgebungen sind und insbesondere keine Gruppe darstellen. Du musst also nichts weiter tun, als Deine \DefineTemplateSection-Definition durch meine zu ersten, damit Dein Beispiel funktioniert. Die Definition von \provideenvironment kannst Du dann natürlich auch gleich rauswerfen, weil Du die dann nicht mehr brauchst.

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

Beitrag von pospiech »

Stimmt, es funktioniert soweit.

Aber: es gibt Pakete die doch von anderen Paketen geladen werden.
Um gezielt einzelen Pakete am Laden zu hindern (vor allem zum debuggen) wäre es hilfreich wenn man das einzeln einschränken könnte.

Das was ich mir vorstelle wäre dann sowas:
% disable loading of package
\DisablePackage{hyperref}
% oder
\DisablePackages{hyperref,microtype}

\usepackage{hyperref,microtype} % wird beides nicht geladen
kann man \usepackage 'gefahrlos' umdefinieren?

Was ich mir vorstelle ist sowas wie das hier - was anscheint sogar funktioniert, nur das ich nicht weiß wie man auf existenz von boolean tested
\documentclass[]{article}

\RequirePackage{ifthen}
\makeatletter
\providecommand\createboolean[2]{%
   \newboolean{#1}\setboolean{#1}{#2}
}%
\let\usepackage\template@usepackage
\providecommand{\usepackage}[2][]{%
  \ifthenelse{\boolean{ifload@#2}}{
	  \template@usepackage[#1]{#2}
  }{
    % package not loaded
  }
}
\providecommand{\DisablePackage}[1]{%
  \createboolean{ifload@#1}{false}%
}%
\providecommand{\EnablePackage}[1]{%
  \createboolean{ifload@#1}{true}%
}%

\makeatother

%\DisablePackage{graphicx}
\usepackage{graphicx}


\listfiles

\begin{document}
\end{document}



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

Beitrag von KOMA »

Zunächst darfst Du in dem Fall nicht \usepackage umdefinieren, sondern solltest \RequirePackage angehen. Innerhalb von Paketen wird nämlich damit gearbeitet. Dann hast Du natürlich das Problem, dass Dir Optionen ggf. als unbenutzt gemeldet werden, die nur von den deaktivierten Paketen ausgewertet werden. Hierfür gibt es keine wirklich gute Lösung, sondern Du musst entscheiden, ob Du generell keine solche Warnungen willst, oder aber diese Warnungen einfach unbeachtet lassen willst.

Ich würde persönlich zur zweiten Lösung tendieren. In dem Fall würde ich einen etwas anderen Ansatz verwenden, als Du, nämlich eher etwas wie in Richtung \ignorepackages{Paket1,Paket2,Paket3,...}. Um eine solche Lösung zu testen, brauche ich allerdings noch etwas Zeit (ich suche gerade danach, ab welcher Kernel-Version das acpi-Modul bei mir einen hard-lock verursacht und habe deshalb immer nur kleine Portionen an Zeit zwischendurch).

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

Beitrag von KOMA »

\documentclass{article}

\makeatletter
\newcommand*{\@excludepackages}{}
\let\@excludepackages\@empty% eigentlich nicht notwendig, aber wer weiß, was
                            % \newcommand noch alles anstellt.
\newcommand*{\excludepackages}[1]{%
  \edef\@excludepackages{\@excludepackages,\zap@space#1 \@empty}%
}
\newcommand*{\OriginalRequirePackage}{}
\let\OriginalRequirePackage\RequirePackage
\renewcommand*{\RequirePackage}[2][]{%
  \typeout{TRACE: Mein \string\RequirePackage}%
  \ifx\@excludepackages\@empty% Keine Ausnahmen
    \typeout{TRACE: Keine Ausnahmen}%
    \edef\reserved@c{,#2}%
  \else
    % Alle Pakete durchgehen (wir erinnern und, dass das Argument von
    % \RequirePackage eine Liste sein kann):
    \let\reserved@c\@empty% Neue Ladeliste
    \@for\reserved@b:=#2\do {%
      \begingroup
        \@tempswatrue % Paket laden
        \@for\reserved@a:=\@excludepackages\do {% Liste der ausgenommenen Pakete
                                                % durchgehen 
          \ifx\reserved@a\reserved@b % Das aktuelle Paket ist in der Liste
            \@tempswafalse % Paket nicht laden
          \fi
        }%
        \if@tempswa
          \xdef\reserved@c{\reserved@c,\reserved@b}%Paket in die neue Liste
        \fi
      \endgroup
    }%
  \fi
  % Übrige Pakete laden, dabei das Komma am Anfang der Liste entfernen.
  \edef\reserved@a{\noexpand\OriginalRequirePackage[#1]{%
      \expandafter\@gobble\reserved@c\@empty}}%
  \reserved@a
}
\ifx\usepackage\OriginalRequirePackage
  \let\usepackage\RequirePackage% Das macht LaTeX selbst auch,
                      % muss aber wiederholt werden, weil sonst das
                      % alte \RequirePackage (also \OriginalRequirePackage)
                      % für \usepackage verwendet wird.
\else
  % Hier fehlt noch eine Fehlerbehandlung bezüglich eines unerwartet
  % (durch irgend ein anderes Paket) umdefinierten \usepackage
\fi
\makeatother

\excludepackages{scrlfile}
% Die folgende Zeile ergibt einen Fehler, weil typearea auf scrlfile
% angewiesen ist, wir das Laden dieses Pakets aber verboten haben.
\usepackage{scrbase,scrlfile,typearea}

\begin{document}

\end{document}

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

Beitrag von pospiech »

Erstmal vielen Dank für diesen sehr gut dokumentierten Code!
KOMA hat geschrieben: Ich würde persönlich zur zweiten Lösung tendieren. In dem Fall würde ich einen etwas anderen Ansatz verwenden, als Du, nämlich eher etwas wie in Richtung \ignorepackages{Paket1,Paket2,Paket3,...}.
Mir ist nicht ganz klar ob deine letzte Lösung deiner Idee von \ignorepackages entspricht, oder ob du damit noch etwas anderes im Sinn hattest.

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

Beitrag von KOMA »

pospiech hat geschrieben:Mir ist nicht ganz klar ob deine letzte Lösung deiner Idee von \ignorepackages entspricht
Genau. Ich habe nur das Makro stattdessen \excludepackages genannte.

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

Beitrag von pospiech »

Ich wollte die Variante mit \newif \if usw mal ausprobieren und habe folgendes versucht:
\documentclass{article}

\providecommand{\DefineTemplateSectionX}[2][true]{%
  \newif\ifTemplateSection#2
  \TemplateSection#2#1
  % \createboolean{bool@templatesection@#2}{#1}%
}%
\providecommand{\SetTemplateSectionX}[2]{%
  \TemplateSection#2#1
  %\setboolean{bool@templatesection@#2}{#1}%
}%
\providecommand{\BeginTemplateSection}[1]{%
	\ifTemplateSection#1
}
\providecommand{\EndTemplateSection}[1]{%
	\fi
}

\DefineTemplateSectionX[true]{PackagesBase}

\begin{document}
Hello
\BeginTemplateSection{PackagesBase}
World
\EndTemplateSection{PackagesBase}
\end{document}
Wenn ich im Dokument nun versuche ein \if zu definieren, dann bekomme ich aber eine Fehlermeldung
l.19 \DefineTemplateSectionX[true]{PackagesBase}
You're in trouble here. Try typing <return> to proceed.
If that doesn't work, type X <return> to quit.
! Undefined control sequence.
\\DefineTemplateSectionX ...n #2 \TemplateSection
#2#1
l.19 \DefineTemplateSectionX[true]{PackagesBase}
The control sequence at the end of the top line
of your error message was never \def'ed.
was mache ich falsch?

Antworten