summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pkgloader
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/pkgloader
Initial commit
Diffstat (limited to 'macros/latex/contrib/pkgloader')
-rw-r--r--macros/latex/contrib/pkgloader/README53
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-cls-pkg.sty24
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-dry.sty54
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-early.sty24
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-error.sty60
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-false.sty25
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-late.sty24
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-packagedoc.cls392
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-recommended.sty274
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader-true.sty23
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader.pdfbin0 -> 469532 bytes
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader.sty1017
-rw-r--r--macros/latex/contrib/pkgloader/pkgloader.tex386
13 files changed, 2356 insertions, 0 deletions
diff --git a/macros/latex/contrib/pkgloader/README b/macros/latex/contrib/pkgloader/README
new file mode 100644
index 0000000000..3765933955
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/README
@@ -0,0 +1,53 @@
+latex-pkgloader
+===============
+
+LaTeX Package : latex-pkgloader 0.7.0
+
+Last Modified : 2018-04-29
+
+Author : Michiel Helvensteijn (www.mhelvens.net)
+
+CTAN page : https://www.ctan.org/pkg/pkgloader
+
+
+Summary
+-------
+
+A LaTeX package for managing the options and loading order of other packages
+
+
+Prerequisites
+-------------
+
+To use this package you need, apart from packages installed by default,
+the following package:
+
+* `lt3graph`
+
+To generate the documentation some additional packages are needed.
+
+
+Installation
+-------------
+
+`pkgloader.sty` is provided directly in the package archive. Put
+it in a place where your LaTeX distribution can find it.
+(`pkgloader.sty` is not generated, but manually maintained; you
+ may use docstrip to remove the documentation, but you don't
+ have to; it will just work the way it is)
+
+
+Documentation
+-------------
+
+`pkgloader.pdf` is provided directly in the package archive or [via CTAN](http://mirrors.ctan.org/macros/latex/contrib/pkgloader/pkgloader.pdf).
+To generate the documentation yourself, run LaTeX on pkgloader.tex.
+(`pkgloader.tex` does not contain the package code itself; it inputs
+ `pkgloader.sty` directly to document the implementation)
+
+License
+-------
+
+This material is subject to the LaTeX Project Public License. See
+http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
+for the details of that license.
diff --git a/macros/latex/contrib/pkgloader/pkgloader-cls-pkg.sty b/macros/latex/contrib/pkgloader/pkgloader-cls-pkg.sty
new file mode 100644
index 0000000000..2849c8098e
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-cls-pkg.sty
@@ -0,0 +1,24 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+% %
+% This file is always loaded before the '\usepackage' %
+% requested packages and after all classes. It's %
+% really just a stub in the dependency graph. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/macros/latex/contrib/pkgloader/pkgloader-dry.sty b/macros/latex/contrib/pkgloader/pkgloader-dry.sty
new file mode 100644
index 0000000000..ea2b6f5557
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-dry.sty
@@ -0,0 +1,54 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-lt3graph %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status 'maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+
+% I will 'officially' release this file at some point in the future. For
+% now I'm just using it to document a couple of packages. Still, it's
+% released under LPPL, so use it as you will.
+%
+% -- Michiel Helvensteijn
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{dry}
+ [2013/10/11 convenience macros for reusing LaTeX code]
+
+\RequirePackage{filecontents}
+\RequirePackage{xparse}
+\RequirePackage{etoolbox}
+\RequirePackage{withargs}
+
+\newcommand\minput[1]{%
+ \input{#1}\unskip%
+}
+
+\NewDocumentCommand{\NewDRYer}{m +m}{%
+ \withargs [\uniquecsname] [#2] {%
+ \newenvironment{#1}{%
+ \begingroup%
+ \@tempswafalse\filec@ntents{##1.tmp}%
+ }{%
+ \endfilecontents%
+ \endgroup%
+ }%
+ \AfterEndEnvironment{#1}{%
+ \withargs (xn) [##1.tmp] [\minput{##1.tmp}] {%
+ ##2%
+ }%
+ }%
+ }%
+}
diff --git a/macros/latex/contrib/pkgloader/pkgloader-early.sty b/macros/latex/contrib/pkgloader/pkgloader-early.sty
new file mode 100644
index 0000000000..b374a12373
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-early.sty
@@ -0,0 +1,24 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+% %
+% This file is always loaded after the 'early' %
+% packages but before every other package. It's %
+% really just a stub in the dependency graph. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/macros/latex/contrib/pkgloader/pkgloader-error.sty b/macros/latex/contrib/pkgloader/pkgloader-error.sty
new file mode 100644
index 0000000000..7ec796ef6e
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-error.sty
@@ -0,0 +1,60 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+% %
+% This file is loaded whenever a combination of packages is %
+% requested that has been marked as illegal. Loading this %
+% file always results in the termination of the LaTeX run. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%% Back to expl3 syntax
+%
+\ExplSyntaxOn
+
+
+%%% Add an empty line to the log before the errors are printed
+%
+\typeout{}
+
+
+%%% Initialization for the error-message loop
+%
+\cs_generate_variant:Nn \int_step_inline:nnnn {nnvn}
+\cs_generate_variant:Nn \int_compare:nNnTF {nNvTF}
+\cs_generate_variant:Nn \msg_error:nnnn {nnvv}
+
+
+%%% The loop issues one error message for each reason the
+%%% package combination is illegal. None of them are
+%%% critical or fatal errors; we terminate the run manually.
+%
+\int_step_inline:nnvn {1} {1} {g__pkgloader_count_(pkgloader-error.sty)_int} {
+ \bool_if:cT {g__pkgloader_used_(pkgloader-error.sty)_(#1)_bool} {
+ \msg_error:nnvv
+ {pkgloader} {illegal-combination}
+ {g__pkgloader_condition_(pkgloader-error.sty)_(#1)_tl}
+ {g__pkgloader_reason_ (pkgloader-error.sty)_(#1)_tl}
+ }
+}
+
+
+%%% Terminate the LaTeX run
+%
+\stop\bye
diff --git a/macros/latex/contrib/pkgloader/pkgloader-false.sty b/macros/latex/contrib/pkgloader/pkgloader-false.sty
new file mode 100644
index 0000000000..d83e5808d1
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-false.sty
@@ -0,0 +1,25 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+% %
+% This file is never loaded by pkgloader, and that's its %
+% only function: to be 'false' in loading conditions. %
+% Basically, the file exists to reserve the name %
+% 'pkgloader-false'. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/macros/latex/contrib/pkgloader/pkgloader-late.sty b/macros/latex/contrib/pkgloader/pkgloader-late.sty
new file mode 100644
index 0000000000..601196a6b9
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-late.sty
@@ -0,0 +1,24 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+% %
+% This file is always loaded before the 'late' %
+% packages but after every other package. It's %
+% really just a stub in the dependency graph. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/macros/latex/contrib/pkgloader/pkgloader-packagedoc.cls b/macros/latex/contrib/pkgloader/pkgloader-packagedoc.cls
new file mode 100644
index 0000000000..eb81fc4dcf
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-packagedoc.cls
@@ -0,0 +1,392 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-lt3graph %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status 'maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\let\packagename\jobname
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Document Class %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\LoadClassWithOptions{l3doc}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Importing The Main Package %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\RequirePackage{pkgloader}
+ \RequirePackage{array}
+ \RequirePackage{etoolbox}
+ \RequirePackage[table]{xcolor}
+ \RequirePackage[xcolor]{mdframed}
+ \RequirePackage{marginnote}
+ \RequirePackage{listings}
+ \RequirePackage{textcomp}
+ \RequirePackage{hyperref}
+ \RequirePackage{needspace}
+ \RequirePackage{noindentafter}
+ \RequirePackage{pkgloader-dry}
+\LoadPackagesNow
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Documentation Options %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\verbatimchar{"} % because the macro \& is being indexed
+
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% File Info %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\extratitlenote{}
+
+\GetFileInfo{\packagename.sty}
+
+\title{
+ The \textsf{\packagename} package\thanks{%
+ This document corresponds to
+ \textsf{\packagename}~\fileversion,
+ dated \filedate.
+ }
+ \ifdefempty{\extratitlenote}{}{\thanks{\extratitlenote}}
+}
+
+\author{
+ Michiel Helvensteijn\\
+ \href{mailto:mhelvens+latex@gmail.com}{mhelvens+latex@gmail.com}
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Development Info %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newmdenv[
+ leftline = false,
+ rightline = false
+]{bannerframe}
+
+\apptocmd{\maketitle}{
+ \begin{bannerframe}
+ \small
+ \begin{center}
+ Development of this package is organized at
+ \href{https://github.com/mhelvens/latex-\packagename}
+ {github.com/mhelvens/latex-\packagename}.\\
+ I am happy to receive feedback there!
+ \end{center}
+ \end{bannerframe}
+}{}{}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Example Environment Setup %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\renewcommand{\ttdefault}{pcr}
+
+\lstdefinelanguage{latex}{
+ language=[LaTeX]tex,
+ alsoletter={_,:},
+ morekeywords={before,after,late,early,if,
+ error,always,because,loaded},
+ moretexcs={RequirePackage,RequirePackageWithOptions,%
+ LoadClass,LoadClassWithOptions,%
+ Load,LoadPackagesNow},
+ mathescape,
+ texcsstyle=*\bfseries
+}
+
+\lstset{
+ language=latex,
+ escapechar=|,
+ basicstyle=\ttfamily\upshape,
+ keywordstyle=\ttfamily\upshape\bfseries,
+ keywordstyle=[2]\color{green!40!black},
+ keywordstyle=[3]\itshape,
+ commentstyle=\color{gray},
+ numbers=left,
+ numberstyle=\footnotesize,
+ frame=none,
+ columns=fixed,
+ literate={[} {\bfseries[} 1
+ {]} {\bfseries]} 1
+ {\{} {\bfseries\{} 1
+ {\}} {\bfseries\}} 1
+ {(} {\bfseries(} 1
+ {)} {\bfseries)} 1
+ {\&\&} {\bfseries\&\&} 2
+ {||} {\bfseries||} 2
+ {!} {\bfseries!} 1
+ {,} {\bfseries,} 1
+}
+
+%%% Environments
+
+\lstnewenvironment{latex}[1][]{
+ \lstset{language=latex, #1}
+}{}
+\NoIndentAfterEnv{latex}
+
+%%% File Input Command
+
+\NewDocumentCommand\inputlatexcode{ O{} m }{%
+ \lstinputlisting[%
+ language=latex,
+ literate={[} {\bfseries[} 1
+ {]} {\bfseries]} 1
+ {\{} {\bfseries\{} 1
+ {\}} {\bfseries\}} 1
+ {(} {\bfseries(} 1
+ {)} {\bfseries)} 1
+ {\&\&} {\bfseries\&\&} 2
+ {||} {\bfseries||} 2
+ {!} {\bfseries!} 1
+ {,} {\bfseries,} 1, #1
+ ]{#2}%
+ \NoIndentAfterThis%
+}
+
+
+%%% Code formatting
+
+\lstdefinestyle{examplecode}{%
+ language=latex,%
+ basicstyle=\ttfamily\small,%
+ texcsstyle=*\bfseries,%
+ keywordstyle=\bfseries%
+}
+\lstMakeShortInline[style=examplecode]|
+
+%%% Setting up example code block
+
+\definecolor{examplecodelinecolor}{rgb}{0,0,0}
+\definecolor{examplecodebackgroundcolor}{rgb}{.9,.9,.9}
+\newmdenv[
+ linecolor = examplecodelinecolor,
+ backgroundcolor = examplecodebackgroundcolor,
+ skipabove = 0bp,
+ skipbelow = 0bp,
+ innertopmargin = -3bp,
+ innerrightmargin = 4bp,
+ innerbottommargin = -3bp,
+ innerleftmargin = 4bp
+]{examplecodeframe}
+
+%%% Defining example output block
+
+\definecolor{exampleoutputbackgroundcolor}{rgb}{1,1,1}
+\newmdenv[
+ linecolor = examplecodelinecolor,
+ backgroundcolor = exampleoutputbackgroundcolor,
+ skipabove = 0bp,
+ skipbelow = 0bp,
+ innertopmargin = 4bp,
+ innerrightmargin = 4bp,
+ innerbottommargin = 4bp,
+ innerleftmargin = 4bp
+]{exampleoutputframe}
+
+%%% Macros for counting lines in file, adapted from
+%%% http://andreas.scherbaum.la/blog/archives/
+%%% 670-Read-number-lines-in-a-file-in-LaTeX.html
+%
+\RequirePackage{ifthen}
+\newboolean{packagedoc@restfile}
+\newcommand*{\packagedoc@fileline}{}
+\newread\packagedoc@file
+\newcommand*{\packagedoc@readnextline}[1]{%
+ \ifthenelse{\boolean{packagedoc@restfile}}{%
+ \read#1 to \packagedoc@fileline%
+ \ifeof#1\setboolean{packagedoc@restfile}{false}%
+ \else\fi%
+ }{}%
+}
+\newcommand*{\countlinesinfile}[2]{%
+ \setboolean{packagedoc@restfile}{true}%
+ \setcounter{packagedoc@linecount}{0}%
+ \openin\packagedoc@file=#1%
+ \whiledo{\boolean{packagedoc@restfile}}{%
+ \packagedoc@readnextline{\packagedoc@file}%
+ \ifthenelse{\boolean{packagedoc@restfile}}{%
+ \stepcounter{packagedoc@linecount}%
+ }{}%
+ }%
+ \closein\packagedoc@file%
+ \edef#2{\thepackagedoc@linecount}%
+}
+
+\newcounter{packagedoc@linecount}
+\newlength{\packagedoc@spacetoreserve}
+
+%%% DRYer without output
+%
+\NewDRYer{latex-example}{%
+ \addvspace{4bp}%
+ {%
+ \ttfamily\small%
+ \countlinesinfile{#1}{\countedlines}%
+ \setlength{\packagedoc@spacetoreserve}{\countedlines\baselineskip}%
+ \setlength{\packagedoc@spacetoreserve}{1.7\packagedoc@spacetoreserve}%
+ \addtolength{\packagedoc@spacetoreserve}{-4bp}%
+ \needspace{\packagedoc@spacetoreserve}%
+ }%
+ \begin{examplecodeframe}%
+ \renewcommand{\ttdefault}{pcr}%
+ \lstinputlisting[style=examplecode]{#1}%
+ \end{examplecodeframe}%
+ #2%
+ \addvspace{4bp}%
+}
+\NoIndentAfterEnv{latex-example}
+
+%%% DRYer WITH output but WITHOUT side-effects
+%
+\NewDRYer{latex-example-show}{%
+ \addvspace{4bp}%
+ {%
+ \ttfamily\small%
+ \countlinesinfile{#1}{\countedlines}%
+ \setlength{\packagedoc@spacetoreserve}{\countedlines\baselineskip}%
+ \setlength{\packagedoc@spacetoreserve}{1.7\packagedoc@spacetoreserve}%
+ \addtolength{\packagedoc@spacetoreserve}{\baselineskip}%
+ \needspace{\packagedoc@spacetoreserve}%
+ }%
+ \begin{examplecodeframe}%
+ \renewcommand{\ttdefault}{pcr}%
+ \lstinputlisting[style=examplecode]{#1}%
+ \end{examplecodeframe}\vspace{-4bp}%
+ \begin{exampleoutputframe}%
+ #2%
+ \end{exampleoutputframe}%
+ \addvspace{4bp}%
+}
+\NoIndentAfterEnv{latex-example-show}
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Implementation Code Box Setup %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%% Saving old implementation code block font
+%
+\AtBeginDocument{\let\old@macro@font\macro@font}
+
+%%% Setup for 'interesting' implementation code blocks
+%
+\definecolor{interestingcodebackgroundcolor}{rgb}{.9,.9,.9}
+\definecolor{interestingcodelinecolor}{rgb}{0,0,0}
+\mdfdefinestyle{interestingcode}{
+ linecolor = interestingcodelinecolor,
+ backgroundcolor = interestingcodebackgroundcolor
+}
+\newcommand*{\interesting}{%
+ \def\codestyle{interestingcode}%
+ \let\macro@font\old@macro@font%
+}
+
+%%% Setup for 'UNinteresting' implementation code blocks
+%
+\definecolor{uninterestingcodebackgroundcolor}{rgb}{.97,.97,.97}
+\definecolor{uninterestingcodelinecolor}{rgb}{.5,.5,.5}
+\definecolor{uninterestingcodecolor}{rgb}{.4,.4,.4}
+\mdfdefinestyle{uninterestingcode}{
+ linecolor = uninterestingcodelinecolor,
+ backgroundcolor = uninterestingcodebackgroundcolor,
+}
+\newcommand*{\uninteresting}{%
+ \def\codestyle{uninterestingcode}%
+ \def\macro@font{\color{uninterestingcodecolor}\old@macro@font}%
+ \vskip-\belowdisplayskip%
+ \vskip-1.05\abovedisplayskip%
+}
+
+\BeforeBeginEnvironment{macrocode}{\lstDeleteShortInline|\vskip.2\abovedisplayskip}
+
+%%% Actually surround 'macrocode' with the frame
+%
+\surroundwithmdframed[
+ style = \codestyle,
+ skipabove = 0bp,
+ skipbelow = 0bp,
+ splitbottomskip = 4bp,
+ innertopmargin =-3bp,
+ innerrightmargin = 1bp,
+ innerbottommargin = 4bp,
+ innerleftmargin = 1bp
+]{macrocode}
+
+%%% Start out with 'interesting' code status and
+%%% always go back to it after one code block
+%
+\interesting
+\AfterEndEnvironment{macrocode}{\lstMakeShortInline[style=examplecode]|\vskip\belowdisplayskip\interesting\NoIndentAfterThis}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Argument Specifiers and such %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newcommand*{\movarg}[1]{[ \texttt{#1} ]}
+\newcommand*{\momarg}[1]{[ \meta{#1} ]}
+
+\newcommand{\describemacro}[2]{%
+ \needspace{3\baselineskip}%
+ \noindent\\\DescribeMacro{#1} #2\\\NoIndentAfterThis%
+}
+
+\newcommand{\describeanymacro}[2]{%
+ \needspace{3\baselineskip}%
+ \noindent\\\marginnote{#1} #2\\\NoIndentAfterThis%
+}
+
+\newcommand{\describemetamacro}[2]{%
+ \describeanymacro{\meta{#1}}{#2}%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Other Stuff %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\NoIndentAfterEnv{description}
+\NoIndentAfterEnv{itemize}
+\NoIndentAfterEnv{enumerate}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Automatic Implementation Docs %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\AtEndDocument{
+ \pagebreak
+
+ \renewcommand{\ttdefault}{cmtt}
+
+ \section{Implementation} \label{sec:implementation}
+
+ \StopEventually {\PrintChanges}
+
+ We now show and explain the entire implementation from \texttt{\packagename.sty}.
+
+ \DocInput{\packagename.sty}
+
+ \Finale
+
+ \PrintIndex
+}
diff --git a/macros/latex/contrib/pkgloader/pkgloader-recommended.sty b/macros/latex/contrib/pkgloader/pkgloader-recommended.sty
new file mode 100644
index 0000000000..db98c07cd4
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-recommended.sty
@@ -0,0 +1,274 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `author-maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <http://www.macfreek.nl/memory/LaTeX_package_conflicts>:
+%
+% \begin{macrocode}
+\Load {fixltx2e} early if loaded
+\Load {fancyhdr} before {hyperref} if loaded
+\Load {fncychap} before {hyperref} if loaded
+\Load {float} before {hyperref} if loaded
+\Load {hyperref} before {algorithm} if loaded
+\Load {amssymb} before {xunicode} if loaded
+\Load {amssymb} before {xltxtra} if loaded
+\Load {graphicx} before {xltxtra} if loaded
+\Load {graphicx} before {fontspec} if loaded
+\Load {caption} before {subfig} if loaded
+\Load {amsmath} before {wasysym} if loaded
+\Load {todonotes} before {program} if loaded
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules extracted from the cleveref
+% documentation and uses of |\@ifpackageloaded| in
+% |cleveref.sty|:
+%
+% \begin{macrocode}
+\Load {cleveref} after {algorithm2e,algorithmicx,
+ aliascnt,amsmath,amsthm,caption,
+ hyperref,IEEEtrantools,listings,
+ ntheorem,subfig,varioref}
+ if loaded
+ because {cleveref adds special support
+ for this package}
+\Load {cleveref} before {autonum,hypdvips}
+ if loaded
+ because {the cleveref documentation
+ explicitly says to do so}
+\Load {varioref} before {hyperref}
+ if {varioref && hyperref && cleveref}
+ because {the cleveref documentation
+ explicitly requires varioref
+ before hyperref if all three
+ packages are loaded}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <http://mirrors.dotsrc.org/ctan/macros/latex/contrib/natbib/natbib.pdf>:
+%
+% \begin{macrocode}
+\Load {natbib} before {citeref}
+ if loaded
+ because {the natbib documentation
+ explicitly requires citeref to
+ be load after natbib}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <http://mirrors.dotsrc.org/ctan/biblio/bibtex/contrib/apacite/apacite.pdf>:
+%
+% \begin{macrocode}
+\Load {babel} before {apacite}
+ if loaded
+ because {babel's selectlanguage redefines
+ refname and bibname}
+\Load {hyperref} before {apacite}
+ if loaded
+ because {hyperref redefines citation and
+ reference list commands}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <http://tex.stackexchange.com/questions/64585/incompatibilities-of-cmap-with-fontenc-hyperref/64605#64605>:
+%
+% \begin{macrocode}
+\Load {hyperref} before {cmap}
+ if loaded
+ because {hyperref cannot write pdf settings
+ if cmap already wrote to pdf}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <ftp://ftp.tex.ac.uk/tex-archive/macros/latex/contrib/hyperref/README.pdf>:
+%
+% \begin{macrocode}
+\Load {hyperref} before {ellipsis,amsrefs,chappg,dblaccnt,
+ linguex}
+ if loaded
+ because {the hyperref documentation
+ explicitly says to do so}
+\Load {hyperref} after {multind,natbib,setspace}
+ if loaded
+ because {the hyperref documentation
+ explicitly says to do so}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <http://mirrors.dotsrc.org/ctan/macros/latex/contrib/glossaries/glossaries-user.pdf>,
+% <http://mirrors.dotsrc.org/ctan/macros/latex/contrib/glossaries/glossariesbegin.pdf>:
+%
+% \begin{macrocode}
+\Load {hyperref} before {glossaries}
+ if loaded
+ because {otherwise terms won't be
+ clickable hyperlinks}
+\Load {glossaries} after {babel,polyglossia,inputenc,
+ fontenc,doc}
+ if loaded
+ because {the glossaries documentation
+ explicitly says to do so}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <http://mirrors.dotsrc.org/ctan/macros/latex/contrib/oberdiek/hypcap.pdf>:
+%
+% \begin{macrocode}
+\Load {hyperref} before {hypcap}
+ if loaded
+ because {hypcap redefines hyperref's
+ caption command}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <https://tex.stackexchange.com/questions/419218/how-to-use-selnolig-package-together-with-default-lualalatex-font#comment1049043_419218>:
+%
+% \begin{macrocode}
+\Load {babel} before {selnolig}
+ if loaded
+ because {this was recommended by selnolig's author}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <https://tex.stackexchange.com/questions/64409/proper-use-of-cmap-and-mmap/64457#64457>:
+%
+% \begin{macrocode}
+\Load {fontenc} after {cmap,mmap}
+ if loaded
+ because {otherwise some fonts may be unprocessed}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <https://ctan.org/pkg/listingsutf8>:
+%
+% \begin{macrocode}
+\Load {listingsutf8} after {listings}
+ if loaded
+ because {it patches macros defined by listings}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from the cleveref code:
+%
+% \begin{macrocode}
+\Load {glossaries} before {cleveref}
+ if loaded
+ because {glossaries loads amsmath, which needs to be loaded before cleveref}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from the refenums
+% documentation and code:
+%
+% \begin{macrocode}
+\Load {refenums} after {hyperref,cleveref,csquotes,ifthen}
+ if loaded
+ because {it prevents an options clash}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules derived from
+% <http://texdoc.net/pkg/microtype> (v2.7a, page 23):
+%
+% \begin{macrocode}
+\Load {babel} before {microtype}
+ if loaded
+ because {microtype can use the language setting of babel}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% A list of recommended rules extracted from:
+% <http://texdoc.net/pkg/uri> (section 2) and uses of
+% |\@ifpackageloaded| and |\RequirePackage| in |uri.sty|:
+%
+% \begin{macrocode}
+\Load {hyperref} before {uri}
+ if loaded
+ because {uri uses hyperref's commands if hyperref is loaded}
+\Load {url} before {uri}
+ if loaded
+ because {uri has a RequirePackage on url}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/macros/latex/contrib/pkgloader/pkgloader-true.sty b/macros/latex/contrib/pkgloader/pkgloader-true.sty
new file mode 100644
index 0000000000..b949a504a4
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader-true.sty
@@ -0,0 +1,23 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+% %
+% This file is always loaded by pkgloader, and that's its %
+% only function: to be 'true' in loading conditions. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/macros/latex/contrib/pkgloader/pkgloader.pdf b/macros/latex/contrib/pkgloader/pkgloader.pdf
new file mode 100644
index 0000000000..1f58729110
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader.pdf
Binary files differ
diff --git a/macros/latex/contrib/pkgloader/pkgloader.sty b/macros/latex/contrib/pkgloader/pkgloader.sty
new file mode 100644
index 0000000000..66b1613e0d
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader.sty
@@ -0,0 +1,1017 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+
+% \CheckSum{0}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Package Info} %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% First, the mandatory package meta-information:
+%
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\RequirePackage{expl3}
+\ProvidesExplPackage{pkgloader}{2018/04/29}{0.7.0}
+ {managing the options and loading order of LaTeX packages}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Required Packages} %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% The following packages are required. Two standard |expl3|-related
+% packages, one experimental package in |l3regex| and one user-contributed
+% |expl3| package in |lt3graph|:
+%
+% \begin{macrocode}
+\RequirePackage{xparse}
+\RequirePackage{l3keys2e}
+\RequirePackage{l3regex}
+\RequirePackage{lt3graph}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Package Code} %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% We need two global data-structures. One to keep track of all packages
+% that are known, one to keep track of the packages that are actually
+% going to be loaded, and their order:
+%
+% \begin{macrocode}
+\prop_new:N \g__pkgloader_known_pkg_prop
+\graph_new:N \g__pkgloader_pkg_graph
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% We store pristine versions of the three package loading
+% commands:
+%
+% \begin{macrocode}
+\cs_gset_eq:NN \__pkgloader_usepkg:wnw \usepackage
+\cs_gset_eq:NN \__pkgloader_RPkg:wnw \RequirePackage
+\cs_gset_eq:NN \__pkgloader_RPkgWithOptions:wnw \RequirePackageWithOptions
+\cs_gset_eq:NN \__pkgloader_doccls:wnw \documentclass
+\cs_gset_eq:NN \__pkgloader_LCls:wnw \LoadClass
+\cs_gset_eq:NN \__pkgloader_LClsWithOptions:wnw \LoadClassWithOptions
+% \end{macrocode}
+%
+% And we define a command to clean up any and all commands
+% that we change or introduce. It will be called when they
+% are not needed anymore:
+%
+% \begin{macrocode}
+\tl_new:N \__pkgloader_cleanup_commands:
+\tl_put_right:Nn \__pkgloader_cleanup_commands: {
+ \cs_gset_eq:NN \usepackage \__pkgloader_usepkg:wnw
+ \cs_gset_eq:NN \RequirePackage \__pkgloader_RPkg:wnw
+ \cs_gset_eq:NN \RequirePackageWithOptions \__pkgloader_RPkgWithOptions:wnw
+ \cs_gset_eq:NN \documentclass \__pkgloader_doccls:wnw
+ \cs_gset_eq:NN \LoadClass \__pkgloader_LCls:wnw
+ \cs_gset_eq:NN \LoadClassWithOptions \__pkgloader_LClsWithOptions:wnw
+}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This function globally registers a package loading rule,
+% which can be created with either the |\Load| command or
+% any of the hijacked |\usepackage|-like commands:
+%
+% \begin{macrocode}
+\cs_new_protected:Nn \__pkgloader_register_rule:nnnnnnnnn {
+ % #1: package or class name
+ % #2: options
+ % #3: version
+ % #4: condition
+ % #5: compiled condition
+ % #6: packages to load before this one
+ % #7: packages to load after this one
+ % #8: reason
+ % #9: command
+% \end{macrocode}
+%
+% If this package or class hasn't been seen before,
+% register it and create a rule-counter for it:
+%
+% \begin{macrocode}
+ \prop_if_in:NnF \g__pkgloader_known_pkg_prop {#1} {
+ \prop_gput:Nnn \g__pkgloader_known_pkg_prop {#1} {}
+ \int_new:c {g__pkgloader_count_(#1)_int}
+ }
+% \end{macrocode}
+%
+% Increment the rule-counter:
+%
+% \begin{macrocode}
+ \int_incr:c {g__pkgloader_count_(#1)_int}
+% \end{macrocode}
+%
+% Then, we set all properties of the
+%
+% \begin{macrocode}
+ \tl_set:Nf \l_tmpa_tl {\int_use:c {g__pkgloader_count_(#1)_int}}
+ \tl_set:cn {g__pkgloader_options_ (#1)_(\l_tmpa_tl)_tl} {#2}
+ \tl_set:cn {g__pkgloader_version_ (#1)_(\l_tmpa_tl)_tl} {#3}
+ \tl_set:cn {g__pkgloader_condition_ (#1)_(\l_tmpa_tl)_tl} {#4}
+ \tl_set:cn {g__pkgloader_compiled_condition_(#1)_(\l_tmpa_tl)_tl} {#5}
+ \tl_set:cn {g__pkgloader_predecessors_ (#1)_(\l_tmpa_tl)_tl} {#6}
+ \tl_set:cn {g__pkgloader_successors_ (#1)_(\l_tmpa_tl)_tl} {#7}
+ \tl_set:cn {g__pkgloader_reason_ (#1)_(\l_tmpa_tl)_tl} {#8}
+ \tl_set:cn {g__pkgloader_command_ (#1)_(\l_tmpa_tl)_tl} {#9}
+ \bool_new:c {g__pkgloader_used_ (#1)_(\l_tmpa_tl)_bool}
+% \end{macrocode}
+% \uninteresting\begin{macrocode}
+}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% These six macros are redefined to just register
+% the loading information rather than load the
+% package or class immediately. The distinction between
+% package and class is made by prefixing the name
+% with either |.sty| or |.cls| (which will be stripped
+% off before the file is actually loaded):
+%
+% \begin{macrocode}
+\RenewDocumentCommand {\usepackage} { o m o }
+ { \__pkgloader_usepackage_cmd:nnnnnn
+ {\usepackage} {#1} {#2.sty} {#3}
+ {pkgloader-cls-pkg.sty} {} }
+\RenewDocumentCommand {\RequirePackage} { o m o }
+ { \__pkgloader_usepackage_cmd:nnnnnn
+ {\RequirePackage} {#1} {#2.sty} {#3}
+ {} {} }
+\RenewDocumentCommand {\RequirePackageWithOptions} { o m o }
+ { \__pkgloader_usepackage_cmd:nnnnnn
+ {\RequirePackageWithOptions} {#1} {#2.sty} {#3}
+ {} {} }
+\RenewDocumentCommand {\documentclass} { o m o }
+ { \__pkgloader_usepackage_cmd:nnnnnn
+ {\documentclass} {#1} {#2.cls} {#3}
+ {} {pkgloader-cls-pkg.sty} }
+\RenewDocumentCommand {\LoadClass} { o m o }
+ { \__pkgloader_usepackage_cmd:nnnnnn
+ {\LoadClass} {#1} {#2.cls} {#3}
+ {} {pkgloader-cls-pkg.sty} }
+\RenewDocumentCommand {\LoadClassWithOptions} { o m o }
+ { \__pkgloader_usepackage_cmd:nnnnnn
+ {\LoadClassWithOptions} {#1} {#2.cls} {#3}
+ {} {pkgloader-cls-pkg.sty} }
+% \end{macrocode}
+%
+% Storing this information is delegated to the
+% |\__pkgloader_register_rule:nnnnnnnnn| function:
+%
+% \begin{macrocode}
+\cs_new:Nn \__pkgloader_usepackage_cmd:nnnnnn {
+ \__pkgloader_register_rule:nnnnnnnnn
+ {#3} {#2} {#4} % package name, options, version
+ {pkgloader-true.sty} % condition
+ {\c_true_bool} % compiled condition
+ {#5} {#6} % predecessors, successors
+ {it~is~requested~by~the~author} % reason
+ {#1} % command
+}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This is a sophisticated user-level command for manipulating
+% package loading order and conditions. It has a `non-standard'
+% but convenient syntax, which scans for clauses rather than
+% taking standard parameters:
+%
+% \begin{macrocode}
+\NewDocumentCommand {\Load} {} {
+% \end{macrocode}
+%
+% Initialize the variables used for storing given data:
+%
+% \begin{macrocode}
+ \tl_clear:N \l__pkgloader_load_extension_tl
+ \tl_clear:N \l__pkgloader_load_options_tl
+ \tl_clear:N \l__pkgloader_load_name_tl
+ \tl_clear:N \l__pkgloader_load_version_tl
+ \clist_clear:N \l__pkgloader_load_pred_clist
+ \clist_clear:N \l__pkgloader_load_succ_clist
+ \tl_clear:N \l__pkgloader_load_cond_tl
+ \tl_clear:N \l__pkgloader_load_because_tl
+ \tl_clear:N \l__pkgloader_load_cmd_tl
+ \bool_set_false:N \l__pkgloader_early_late_used_bool
+% \end{macrocode}
+%
+% Start scanning for input:
+%
+% \begin{macrocode}
+ \__pkgloader_load_scan_ext_:w
+% \end{macrocode}
+% \uninteresting\begin{macrocode}
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This function checks if the |class| keyword is given.
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_ext_:w {
+ \peek_charcode_remove_ignore_spaces:NTF c {% % % class
+ \__pkgloader_load_scan_ext_c:w
+ }{ % % % % % % % % % % % % % % % % % % % % % % % package details
+ \tl_set:Nn \l__pkgloader_load_extension_tl {.sty}
+ \tl_set:Nn \l__pkgloader_load_cmd_tl {\RequirePackage}
+ \__pkgloader_load_scan_pkg_:w
+ }
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% The |class| keyword indicates that this is a document
+% class loading rule, rather than a package loading rule.
+% We record this and then goes on to scan the details:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_ext_c:w lass {
+ \tl_set:Nn \l__pkgloader_load_extension_tl {.cls}
+ \tl_set:Nn \l__pkgloader_load_cmd_tl {\LoadClass}
+ \clist_put_right:Nn \l__pkgloader_load_succ_clist {pkgloader-cls-pkg.sty}
+ \__pkgloader_load_scan_pkg_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% The following function starts scanning for the name of the package
+% central to this rule, as well as the options and minimum
+% version proposed for it. It also checks if the |error|
+% keyword is given.
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_pkg_:w {
+ \peek_charcode_remove_ignore_spaces:NTF e {% % % error
+ \__pkgloader_load_scan_pkg_e:w
+ }{\peek_charcode_remove_ignore_spaces:NTF [ {% % package options
+ \__pkgloader_load_scan_pkg_options:nw
+ }{ % % % % % % % % % % % % % % % % % % % % % % % package name
+ \__pkgloader_load_scan_pkg_:nw
+ }}
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% The |error| keyword can take the place of a package name,
+% options and version. It is shorthand for the |pkgloader-error|
+% file, and then jumps ahead to scanning clauses:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_pkg_e:w rror {
+ \tl_set:Nn \l__pkgloader_load_name_tl {pkgloader-error.sty}
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This scans the options and goes ahead to scan the package name:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_pkg_options:nw #1 ] {
+ \tl_set:Nn \l__pkgloader_load_options_tl {#1}
+ \__pkgloader_load_scan_pkg_:nw
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This scans the package name (and adds the proper extension),
+% peeks ahead for a minimum version, and otherwise goes on to
+% scanning for clauses:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_pkg_:nw #1 {
+ \tl_set:Nn \l__pkgloader_load_name_tl {#1}
+ \tl_put_right:NV
+ \l__pkgloader_load_name_tl
+ \l__pkgloader_load_extension_tl
+ \peek_charcode_remove_ignore_spaces:NTF [ {% % % % package version
+ \__pkgloader_load_scan_version:nw
+ }{ % % % % % % % % % % % % % % % % % % % % % % % % clauses
+ \__pkgloader_load_scan_clause_:w
+ }
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This scans the version, and then goes ahead to scan for clauses:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_version:nw #1 ] {
+ \tl_set:Nn \l__pkgloader_load_version_tl {#1}
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This is the start- and return-point used to scan
+% for (additional) |\Load| clauses:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_:w {
+ \peek_charcode_remove_ignore_spaces:NTF a {
+ \peek_charcode_remove:NTF l { % % % % % % % % % always
+ \__pkgloader_load_scan_clause_al:w
+ }{\peek_charcode_remove:NTF f { % % % % % % % % after
+ \__pkgloader_load_scan_clause_af:w
+ }{
+ \__pkgloader_load_end: a
+ }}
+ }{\peek_charcode_remove_ignore_spaces:NTF b { %
+ \peek_charcode_remove:NTF e {
+ \peek_charcode_remove:NTF c { % % % % % % % because
+ \__pkgloader_load_scan_clause_bec:w
+ }{\peek_charcode_remove:NTF f { % % % % % % before
+ \__pkgloader_load_scan_clause_bef:w
+ }{
+ \__pkgloader_load_end: be
+ }}
+ }{
+ \__pkgloader_load_end: b
+ }
+ }{\peek_charcode_remove_ignore_spaces:NTF e { % % % early
+ \__pkgloader_load_scan_clause_e:w
+ }{\peek_charcode_remove_ignore_spaces:NTF i { % % % if
+ \__pkgloader_load_scan_clause_i:w
+ }{\peek_charcode_remove_ignore_spaces:NTF l { % % % late
+ \__pkgloader_load_scan_clause_l:w
+ }{
+ \__pkgloader_load_end:
+ }}}}}
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|always|'' clause, which loads this
+% package conditional on the ``|pkgloader-true|'' package being
+% loaded (which always is):
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_al:w ways {
+ \tl_put_right:Nn \l__pkgloader_load_cond_tl {~||~pkgloader-true}
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|after|'' clause:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_af:w ter #1 {
+ \clist_map_inline:nn {#1} {
+ \clist_put_right:Nn \l__pkgloader_load_pred_clist {##1.sty}
+ }
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|because|'' clause:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_bec:w ause #1 {
+ \tl_set:Nn \l__pkgloader_load_because_tl {#1}
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|before|'' clause:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_bef:w ore #1 {
+ \clist_map_inline:nn {#1} {
+ \clist_put_right:Nn \l__pkgloader_load_succ_clist {##1.sty}
+ }
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|early|'' clause, which orders
+% this package before the ``|pkgloader-early|'' stub:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_e:w arly {
+ \bool_set_true:N \l__pkgloader_early_late_used_bool
+ \clist_put_right:Nn \l__pkgloader_load_succ_clist {pkgloader-early.sty}
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|if|'' clause, which may still be
+% a manual condition or the ``|loaded|'' keyword:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_i:w f {
+ \peek_charcode_remove_ignore_spaces:NTF l {
+ \__pkgloader_load_scan_clause_if_l:w
+ }{
+ \__pkgloader_load_scan_clause_if_:nw
+ }
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|if loaded|'' clause, which uses
+% this package being loaded as the condition for the rule being used:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_if_l:w oaded {
+ \tl_put_right:Nn \l__pkgloader_load_cond_tl {~||~}
+ \tl_put_right:NV \l__pkgloader_load_cond_tl \l__pkgloader_load_name_tl
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|if|'' clause with a manual condition:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_if_:nw #1 {
+ \tl_put_right:Nn \l__pkgloader_load_cond_tl {~||~#1}
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%%
+%
+% This processes the ``|late|'' clause, which orders
+% this package after the ``|pkgloader-late|'' stub:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \__pkgloader_load_scan_clause_l:w ate {
+ \bool_set_true:N \l__pkgloader_early_late_used_bool
+ \clist_put_right:Nn \l__pkgloader_load_pred_clist {pkgloader-late.sty}
+ \__pkgloader_load_scan_clause_:w
+}
+% \end{macrocode}
+%
+% %%%%%%%%% %%%%%%%%% %%%%%%%%% %%%%%%%%% %%%%%%%%% %%%%%%%%%
+%
+% This function processes the collected data and registers it:
+%
+% \begin{macrocode}
+\cs_new_protected_nopar:Nn \__pkgloader_load_end: {
+% \end{macrocode}
+%
+% We remove the leading ``\texttt{\ \textbar\textbar\ }'' from the condition:
+%
+% \begin{macrocode}
+ \tl_remove_once:Nn \l__pkgloader_load_cond_tl {~||~}
+% \end{macrocode}
+%
+% If no condition is given at all, the default is: ``|if loaded|''
+%
+% \begin{macrocode}
+ \tl_if_empty:NT \l__pkgloader_load_cond_tl
+ { \tl_set_eq:NN \l__pkgloader_load_cond_tl \l__pkgloader_load_name_tl }
+% \end{macrocode}
+%
+% We now take the condition and compile it to a |\bool_if:|
+% kind of syntax. The original syntax is preserved to use in
+% error messages and such:
+%
+% \begin{macrocode}
+ \tl_set_eq:NN \l__pkgloader_load_compd_cond_tl \l__pkgloader_load_cond_tl
+ \regex_replace_all:nnN
+ { [^\&\|\(\)\!\s]+ }
+ { (\c{graph_if_vertex_exist_p:Nn}
+ \c{g__pkgloader_pkg_graph}\cB\{\0\.sty\cE\}) }
+ \l__pkgloader_load_compd_cond_tl
+% \end{macrocode}
+%
+% If no reason was given for this rule, it was obviously
+% `because of reasons':
+%
+% \begin{macrocode}
+ \tl_if_empty:NT \l__pkgloader_load_because_tl
+ { \tl_set:Nn \l__pkgloader_load_because_tl {of~reasons} }
+% \end{macrocode}
+%
+% Having gathered and processed the data, the rule is
+% registered:
+%
+% \begin{macrocode}
+ \__pkgloader_register_rule:VVVVVVVVV
+ \l__pkgloader_load_name_tl
+ \l__pkgloader_load_options_tl
+ \l__pkgloader_load_version_tl
+ \l__pkgloader_load_cond_tl
+ \l__pkgloader_load_compd_cond_tl
+ \l__pkgloader_load_pred_clist
+ \l__pkgloader_load_succ_clist
+ \l__pkgloader_load_because_tl
+ \l__pkgloader_load_cmd_tl
+% \end{macrocode}
+% \uninteresting\begin{macrocode}
+}
+\cs_generate_variant:Nn \tl_if_eq:nnF {VnF}
+\cs_generate_variant:Nn \graph_gput_vertex:Nn {NV}
+\cs_generate_variant:Nn \graph_gput_edge:Nnn {NnV,NVn}
+\cs_generate_variant:Nn \seq_gput_right:Nn {NV}
+\cs_generate_variant:Nn \__pkgloader_register_rule:nnnnnnnnn {VVVVVVVVV}
+\tl_new:N \l__pkgloader_load_extension_tl
+\tl_new:N \l__pkgloader_load_options_tl
+\tl_new:N \l__pkgloader_load_name_tl
+\tl_new:N \l__pkgloader_load_version_tl
+\clist_new:N \l__pkgloader_load_pred_clist
+\clist_new:N \l__pkgloader_load_succ_clist
+\tl_new:N \l__pkgloader_load_cond_tl
+\tl_new:N \l__pkgloader_load_because_tl
+\tl_new:N \l__pkgloader_load_cmd_tl
+\bool_new:N \l__pkgloader_early_late_used_bool
+% \end{macrocode}
+%
+% %%%%%%%%% %%%%%%%%% %%%%%%%%% %%%%%%%%% %%%%%%%%% %%%%%%%%%
+%
+% And here's the instruction to clean up the
+% |\Load| command-name at the end:
+%
+% \begin{macrocode}
+\tl_put_right:Nn \__pkgloader_cleanup_commands:
+ { \cs_undefine:N \Load }
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This function decides, based on all loaded rules and package
+% requests, which packages, options and versions end up being
+% loaded, and in which order.
+%
+% \begin{macrocode}
+\cs_new_protected:Nn \__pkgloader_select_packages: {
+% \end{macrocode}
+%
+% We first set up a graph to record accepted orderings:
+%
+% \begin{macrocode}
+ \graph_clear:N \l__pkgloader_order_graph
+% \end{macrocode}
+%
+% We then start a loop that runs at least once, then repeats
+% while additional package configurations are still being added
+% to the set. Eventually the loop reaches a fixed point and terminates.
+%
+% \begin{macrocode}
+ \bool_do_while:Nn \l__pkgloader_selection_changed_bool {
+ \bool_set_false:N \l__pkgloader_selection_changed_bool
+% \end{macrocode}
+%
+% Then first, for all possible package configurations (a nested
+% loop, but not doubly indented because it feels like one loop):
+%
+% \begin{macrocode}
+ \prop_map_inline:Nn \g__pkgloader_known_pkg_prop {%%%%%%%%%%%%%% ##1
+ \int_step_inline:nncn {1} {1} {g__pkgloader_count_(##1)_int} {%% ####1
+% \end{macrocode}
+%
+% If the current configuration should be loaded but still
+% isn't selected (nested conditional; but again, not indented):
+%
+% \begin{macrocode}
+ \bool_if:cF {g__pkgloader_used_(##1)_(####1)_bool} {
+ \bool_if:vT {g__pkgloader_compiled_condition_(##1)_(####1)_tl} {
+% \end{macrocode}
+%
+% We mark the package configuration as being used:
+%
+% \begin{macrocode}
+ \bool_set_true:c {g__pkgloader_used_(##1)_(####1)_bool}
+% \end{macrocode}
+%
+% We record the configuration in the main package graph, which maps
+% each package to a clist of selected configurations:
+%
+% \begin{macrocode}
+ \graph_get_vertex:NnNTF \g__pkgloader_pkg_graph {##1}
+ \l__pkgloader_used_configs_tl {
+ \tl_if_empty:NTF \l__pkgloader_used_configs_tl
+ { \graph_gput_vertex:Nnf \g__pkgloader_pkg_graph {##1} {####1} }
+ { \graph_gput_vertex:Nnf \g__pkgloader_pkg_graph {##1}
+ {\l__pkgloader_used_configs_tl, ####1} }
+ } { \graph_gput_vertex:Nnf \g__pkgloader_pkg_graph {##1} {####1} }
+% \end{macrocode}
+%
+% In a separate graph, we record the associated (now activated)
+% package loading orders. We don't do this in the main graph,
+% because it may involve packages that are themselves not yet
+% selected. These edges are later filtered and added to the main graph:
+%
+% \begin{macrocode}
+ \graph_put_vertex:Nn \l__pkgloader_order_graph {##1}
+ \clist_map_inline:cn {g__pkgloader_predecessors_(##1)_(####1)_tl} {
+ \graph_put_vertex:Nn \l__pkgloader_order_graph {########1}
+ \graph_get_edge:NnnNTF \l__pkgloader_order_graph
+ {########1} {##1} \l__pkgloader_used_configs_tl
+ { \graph_put_edge:Nnnn \l__pkgloader_order_graph
+ {########1} {##1} {\l__pkgloader_used_configs_tl,####1} }
+ { \graph_put_edge:Nnnn \l__pkgloader_order_graph
+ {########1} {##1} {####1} }
+ }
+ \clist_map_inline:cn {g__pkgloader_successors_(##1)_(####1)_tl} {
+ \graph_put_vertex:Nn \l__pkgloader_order_graph {########1}
+ \graph_get_edge:NnnNTF \l__pkgloader_order_graph
+ {##1} {########1} \l__pkgloader_used_configs_tl
+ { \graph_put_edge:Nnnn \l__pkgloader_order_graph
+ {##1} {########1} {\l__pkgloader_used_configs_tl,####1} }
+ { \graph_put_edge:Nnnn \l__pkgloader_order_graph
+ {##1} {########1} {####1} }
+ }
+% \end{macrocode}
+%
+% We then mark the change, so a next iteration will be entered:
+%
+% \begin{macrocode}
+ \bool_set_true:N \l__pkgloader_selection_changed_bool
+% \end{macrocode}
+% \uninteresting\begin{macrocode}
+ }}
+ }}
+ }
+% \end{macrocode}
+%
+% We put the applicable proposed orderings into the
+% graph of selected packages:
+%
+% \begin{macrocode}
+ \graph_gput_edges_from:NN \g__pkgloader_pkg_graph \l__pkgloader_order_graph
+% \end{macrocode}
+%
+% If there is a cycle in the derived package loading order: ERROR
+%
+% \begin{macrocode}
+ \graph_if_cyclic:NT \g__pkgloader_pkg_graph
+ { \msg_fatal:nn {pkgloader} {cyclic-order} }
+% \end{macrocode}
+%
+% Finally, we apply some default orderings where needed:
+% \begin{itemize}
+% \item If a package should not specifically
+% go early or late, it goes inbetween; and
+% \item if a package should not specifically
+% go before a class, it goes after.
+% \end{itemize}
+%
+% \begin{macrocode}
+ \graph_map_vertices_inline:Nn \g__pkgloader_pkg_graph {
+ \seq_if_in:NnF \g__pkgloader_system_packages_seq {##1} {
+ \graph_acyclic_if_path_exist:NnnF \g__pkgloader_pkg_graph
+ {##1} {pkgloader-early.sty} {
+ \graph_acyclic_if_path_exist:NnnF \g__pkgloader_pkg_graph
+ {pkgloader-late.sty} {##1} {
+ \graph_put_edge:Nnn \g__pkgloader_pkg_graph {pkgloader-early.sty} {##1}
+ \graph_put_edge:Nnn \g__pkgloader_pkg_graph {##1} {pkgloader-late.sty}
+ } }
+ \graph_acyclic_if_path_exist:NnnF \g__pkgloader_pkg_graph
+ {##1} {pkgloader-cls-pkg.sty} {
+ \graph_put_edge:Nnn \g__pkgloader_pkg_graph {pkgloader-cls-pkg.sty} {##1}
+ } } }
+% \end{macrocode}
+% \uninteresting\begin{macrocode}
+}
+\cs_generate_variant:Nn \int_step_inline:nnnn {nncn}
+\cs_generate_variant:Nn \bool_if:nT {vT}
+\cs_generate_variant:Nn \withargs:nnn {vvn}
+\cs_generate_variant:Nn \graph_gput_vertex:Nnn {Nnf}
+\graph_new:N \l__pkgloader_order_graph
+\tl_new:N \l__pkgloader_used_configs_tl
+\bool_new:N \l__pkgloader_selection_changed_bool
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Now follows the user command to consolidate all package
+% loading requests and do the `right thing' (tm). Invoking
+% this command ends the work of |pkgloader|.
+%
+% \begin{macrocode}
+\NewDocumentCommand {\LoadPackagesNow} {} {
+% \end{macrocode}
+%
+% We first select package configurations by their loading conditions:
+%
+% \begin{macrocode}
+ \__pkgloader_select_packages:
+% \end{macrocode}
+%
+% Now to clean up after |pkgloader|, restoring
+% and removing various command-names.
+%
+% \begin{macrocode}
+ \__pkgloader_cleanup_commands:
+% \end{macrocode}
+%
+% Then, for all used packages, in topological order\ldots
+%
+% \begin{macrocode}
+ \graph_map_topological_order_inline:Nn \g__pkgloader_pkg_graph {
+% \end{macrocode}
+%
+% \ldots load that package. Though note that this code is still quite
+% incomplete, because it loads the first viable configuration. It should:
+% \begin{enumerate}
+% \item use the |WithOptions| version of the command
+% if necessary,
+% \item allow custom merging schemes for options, and
+% \item use the latest required version.
+% \end{enumerate}
+% \begin{macrocode}
+ \withargs:xn { \clist_item:nn{##2}{1} } {
+ \withargs:vvfvn {g__pkgloader_command_(##1)_(####1)_tl}
+ {g__pkgloader_options_(##1)_(####1)_tl}
+ {\__pkgloader_strip_extension:f{##1}}
+ {g__pkgloader_version_(##1)_(####1)_tl} {
+ \IfValueTF {########2}
+ { \IfValueTF {########4}
+ { ########1 [########2] {########3} [########4] }
+ { ########1 [########2] {########3} } }
+ { \IfValueTF {########4}
+ { ########1 {########3} [########4] }
+ { ########1 {########3} } }
+% \end{macrocode}
+% \uninteresting\begin{macrocode}
+ }
+ }
+ }
+}
+\cs_generate_variant:Nn \withargs:nn {xn}
+\cs_generate_variant:Nn \withargs:nnnnn {vvfvn}
+% \end{macrocode}
+%
+% And it needs the following auxiliary function to strip
+% filenames from their four character extension:
+%
+% \begin{macrocode}
+\cs_new:Npn \__pkgloader_strip_extension:f #1 {
+ \tl_reverse:f{
+ \tl_tail:f{\tl_tail:f{\tl_tail:f{\tl_tail:f{
+ \tl_reverse:n{#1}
+ }}}}
+ }
+}
+\cs_generate_variant:Nn \tl_reverse:n {f}
+% \end{macrocode}
+%
+% It's a bit clunky. Is there a substring function
+% in |expl3| we could use that I don't know about?
+%
+% And here's the instruction to clean up the
+% |\LoadPackagesNow| command-name at the end:
+%
+% \begin{macrocode}
+\tl_put_right:Nn \__pkgloader_cleanup_commands:
+ { \cs_undefine:N \LoadPackagesNow }
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+%
+% \begin{macrocode}
+\cs_gset_eq:NN \__pkgloader_begin_env:n \begin
+\RenewDocumentCommand {\begin} {m} {
+ \tl_if_eq:nnT {#1} {document} {\LoadPackagesNow}
+ \__pkgloader_begin_env:n {#1}
+}
+\tl_put_right:Nn \__pkgloader_cleanup_commands:
+ { \cs_gset_eq:NN \begin \__pkgloader_begin_env:n }
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Bootstrap |pkgloader| by inserting |pkgloader-true| in
+% the graph directly, so all other packages can be inserted
+% with rules, possibly using the |always| clause.
+%
+% \begin{macrocode}
+\graph_gput_vertex:Nn \g__pkgloader_pkg_graph {pkgloader-true.sty}
+% \end{macrocode}
+%
+% We keep a list of all pkgloader dummy packages:
+%
+% \begin{macrocode}
+\seq_new:N \g__pkgloader_system_packages_seq
+\cs_generate_variant:Nn \seq_gset_from_clist:Nn {Nx}
+\seq_gset_from_clist:Nx \g__pkgloader_system_packages_seq
+ {\tl_to_str:n
+ {pkgloader-true.sty,
+ pkgloader-false.sty,
+ pkgloader-early.sty,
+ pkgloader-late.sty,
+ pkgloader-cls-pkg.sty}}
+% \end{macrocode}
+%
+% We then register the core logical rules of |pkgloader|,
+% regarding fundamental package `stubs' like |pkgloader-false|,
+% |pkgloader-error|, |pkgloader-early|, and so on.
+%
+% \begin{macrocode}
+\withargs:nn {of~the~mandatory~core~rules~of~pkgloader} {
+ \Load error if {pkgloader-false} because {#1}
+ \Load {pkgloader-true} always because {#1}
+ \Load {pkgloader-early} always because {#1}
+ \Load {pkgloader-late} always because {#1}
+ \Load {pkgloader-cls-pkg} always because {#1}
+ \Load {pkgloader-early} before {pkgloader-late} because {#1}
+}
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% We process the options passed to |pkgloader| as |.sty| files
+% to be loaded before pkgloader does its thing. This
+% should be used to define new |pkgloader| rules. Note,
+% particularly, that any |\usepackage|-like command inside
+% those |.sty| files is registered and processed by
+% |pkgloader|; not loaded directly.
+%
+% First, we define the functions used to handle an option.
+%
+% \begin{macrocode}
+\cs_new:Nn \__pkgloader_process_option:n
+ { \__pkgloader_process_option:nn {#1} {true} }
+\cs_new:Nn \__pkgloader_process_option:nn
+ { \tl_if_eq:nnTF {#2} {true}
+ { \seq_put_right:Nn \l__pkgloader_rule_packages_seq {#1} }
+ { \seq_remove_all:Nn \l__pkgloader_rule_packages_seq {#1} } }
+% \end{macrocode}
+%
+% The |recommended| rules are loaded unless explicitly turned off.
+%
+% \begin{macrocode}
+\seq_new:N \l__pkgloader_rule_packages_seq
+\seq_put_right:Nn \l__pkgloader_rule_packages_seq {recommended}
+% \end{macrocode}
+%
+% Process the options to populate |\l__pkgloader_rule_packages_seq|.
+%
+% \begin{macrocode}
+\cs_generate_variant:Nn \keyval_parse:NNn {NNv}
+\keyval_parse:NNv
+ \__pkgloader_process_option:n
+ \__pkgloader_process_option:nn
+ {opt@pkgloader.sty}
+\seq_remove_duplicates:N \l__pkgloader_rule_packages_seq
+% \end{macrocode}
+%
+% Actually load the |.sty| files in |\l__pkgloader_rule_packages_seq|.
+% Note that the actual file needs the |pkgloader-| prefix.
+%
+% \begin{macrocode}
+\seq_map_inline:Nn \l__pkgloader_rule_packages_seq
+ { \__pkgloader_RPkg:wnw {pkgloader-#1} }
+% \end{macrocode}
+%
+% Finally, we make a show of using the proper macros for \LaTeX's
+% benefit. If we don't, a \LaTeX\ error is issued.
+%
+% \begin{macrocode}
+\DeclareOption*{}
+\ProcessOptions\relax
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Finally, here are the error messages this package can generate.
+% First a simple error for cycles, which should be improved to
+% show the cause of the cycle.
+%
+% \begin{macrocode}
+\msg_new:nnn {pkgloader} {cyclic-order}
+ { There~is~a~cycle~in~the~requested~package~loading~order. }
+% \end{macrocode}
+%
+% And the following is the error reported for certain package
+% combinations that have been forbidden through an |error| rule.
+%
+% \begin{macrocode}
+\msg_new:nnnn {pkgloader} {illegal-combination}
+ { A~combination~of~packages~fitting~the~following~condition~
+ was~requested:
+ \\\\\ \ \ \ #1\\\\
+ This~is~an~error~because~#2. }
+ { A~pkgloader~rule~was~requested~that~prohibits~the~logical~
+ combination\\above~for~the~specified~reason.~It~is~probably~
+ a~good~reason. }
+% \end{macrocode}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/macros/latex/contrib/pkgloader/pkgloader.tex b/macros/latex/contrib/pkgloader/pkgloader.tex
new file mode 100644
index 0000000000..93ffd78080
--- /dev/null
+++ b/macros/latex/contrib/pkgloader/pkgloader.tex
@@ -0,0 +1,386 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%%
+% %
+% Copyright (c) 2018 - Michiel Helvensteijn (www.mhelvens.net) %
+% %
+% https://github.com/mhelvens/latex-pkgloader %
+% %
+% This work may be distributed and/or modified under the conditions %
+% of the LaTeX Project Public License, either version 1.3 of this %
+% license or (at your option) any later version. The latest version %
+% of this license is in http://www.latex-project.org/lppl.txt %
+% and version 1.3 or later is part of all distributions of LaTeX %
+% version 2005/12/01 or later. %
+% %
+% This work has the LPPL maintenance status `maintained'. %
+% %
+% The Current Maintainer of this work is Michiel Helvensteijn. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%%
+
+\documentclass[a4paper]{pkgloader-packagedoc}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Setup %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def\nt#1{\ensuremath{\hbox{\footnotesize$\langle$}\mathit{#1}\hbox{\footnotesize$\rangle$}}}
+\def\|{\ \mid\ }
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Global Changes %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\changes{0.1.0}{2014/01/29}
+ {initial version}
+
+\changes{0.2.0}{2014/05/10}
+ {an important release, which implements most features described in
+ the pkgloader TUGBoat article, and fixes a ton of bugs}
+
+\changes{0.3.0}{2014/08/31}
+ {fixed the package to work with more recent releases of expl3,
+ which removed the individual l3kernel .sty files; additionally,
+ pkgloader now understands preferred loading orders of cleveref}
+
+\changes{0.4.1}{2014/10/26}
+ {integrates a number of new package loading rules contributed by the community}
+
+\changes{0.5.0}{2014/11/30}
+ {integrates a number of new package loading rules contributed by the community}
+
+\changes{0.5.1}{2017/09/20}
+ {fixed the package to work aafter \cs_new:Nn was changed to only allow 'N' and 'n' in function signatures (2016/08/20)}
+
+\changes{0.6.0}{2018/03/24}
+ {integrates a number of new package loading rules contributed by the community}
+
+\changes{0.7.0}{2018/04/29}
+ {integrates a number of new package loading rules contributed by the community}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\begin{document} %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\maketitle
+
+\section {Introduction} % % % % % % % % % % % % % % % % % % % % % % % % % % % %
+
+\LaTeX\ can be extended by loading packages
+using a \lstinline+\usepackage+, \lstinline+\RequirePackage+
+or \lstinline+\RequirePackageWithOptions+ command. Similarly, documents load
+a document class using \lstinline+\documentclass+, \lstinline+\LoadClass+
+or \lstinline+\LoadClassWithOptions+.
+Packages and classes can add definitions, change existing ones,
+or otherwise extend functionality of the language.
+
+While the Turing-complete power of the \TeX\ language is quite useful at times,
+it does make it all too easy for independent package authors to step on each
+others toes. CTAN is full of conceptually independent packages that cannot be
+loaded together, or break if they are not loaded in a specific order.
+
+Yet, until now, there has been no automated package management to speak of.
+Document authors are usually told to avoid certain package combinations,
+or to load packages in some specific order.
+Occasionally, package authors patch their code to be aware of specific
+other packages, circumventing known conflicts.
+But this makes maintenance more difficult, because these package authors
+are `mixing concerns'; they put code related to other packages into their
+own package. And it is all done in an ad-hoc fashion.
+
+Enter \lstinline+pkgloader+.
+
+
+
+\subsection {Package Description} % % % % % % % % % % % % % % % % % % % % % %
+
+Here is an example of main file for a \LaTeX\ document
+which uses \lstinline+pkgloader+:
+
+\newcommand{\morecode}{\hbox{\vphantom{\LARGE(}\smash{\ \small\vdots}}}
+\newcommand{\anyorder}{
+ \smash{\small\hbox{
+ \(
+ \qquad\left.\vrule height 1em depth 1.4em width 0pt\right\}
+ \hbox{\textit{\rmfamily any order}}
+ \)
+} } }
+\newcommand{\optional}{
+ \smash{\small\raisebox{-.7\baselineskip}{
+ \(
+ \qquad\left.
+ \begin{array}{l}\\[.8em]\end{array}
+ \right\}
+ \hbox{\textit{\rmfamily optional}}
+ \)
+} } }
+\begin{latex}
+\RequirePackage{pkgloader}
+ \documentclass{article}
+ \usepackage{algorithm}
+ \usepackage{hyperref} $\anyorder$
+ \usepackage{float}
+\LoadPackagesNow $\hskip44.3pt\optional$
+$\morecode$
+\begin{document} $\hdots$ \end{document}
+\end{latex}
+
+The idea is to load \lstinline+pkgloader+ before loading any other
+package or class.
+It can then intercept all loading requests, analyze them
+and load them properly, taking this burden off the shoulders of
+the average document author.
+
+Between the second and fifth line, the loading of all packages
+and classes is postponed. The \lstinline+\LoadPackagesNow+ command then
+loads the packages in some valid order. This also happens automatically
+upon reaching the end of the preamble. During this process,
+`conflict resolving' code may also be run, meant specifically to make
+other packages work together properly. If the above code were
+compiled without \lstinline+pkgloader+,
+the given package order would cause errors.
+%%
+The main advantage to this approach is that the complexity of dealing
+with package conflicts is moved to the \lstinline+pkgloader+ package and handled
+in a systematic manner.
+
+If you are a document author, this may be all you need to know to use
+\lstinline+pkgloader+. If you are interested in more advanced functionality,
+read on!
+
+
+\subsection {The \texttt{pkgloader} Area} % % % % % % % %
+
+\describeanymacro
+ {\ttfamily\bfseries\textbackslash RequirePackage\!\!\!\!\!}
+ {{\ttfamily{\bfseries\{}pkgloader{\bfseries\}}\quad\ldots\quad{\bfseries\textbackslash LoadPackagesNow}}}
+
+The \lstinline+pkgloader+ area is the area between
+\lstinline+\RequirePackage{pkgloader}+ and
+\lstinline+\LoadPackagesNow+.
+Within it, the three traditional package-loading commands
+are `hijacked', recording information rather than loading
+packages directly. Also, a \lstinline+\Load+ command is
+available, which offers more flexibility in regulating
+package loading behavior.
+
+|pkgloader| accepts sets of rules coming from outside
+packages, though support is still somewhat limited.
+Any |pkgloader-|\nt{something}|.sty| file can be loaded
+within the |pkgloader| area by passing \nt{something}
+as a package option. The file |pkgloader-recommended.sty|
+is loaded this way by default. You can overwrite this by
+passing |recommended=false| as an option. For example:
+
+\begin{latex}
+\RequirePackage[recommended=false, my-better-rules]{pkgloader}
+ $\smash{\raisebox{-1pt}{\small\vdots}}$
+\LoadPackagesNow
+\end{latex}
+
+This area does not play by the recommended package loading
+rules, but uses the rules in |pkgloader-my-better-rules.sty|
+instead.
+
+
+
+\subsection {Package / Class Loading Requests} % % % % % % % %
+
+
+\marginnote{\ttfamily\bfseries\textbackslash usepackage\\
+ \textbackslash RequirePackage\\
+ \textbackslash RequirePackageW{\ldots}s
+ \textbackslash documentclass\\
+ \textbackslash LoadClass\\
+ \textbackslash LoadClassW{\ldots}s}\noindent
+For requesting specific packages or classes inside the
+|pkgloader| area, just use the commands always used
+for this purpose:
+ \lstinline+\usepackage+,
+ \lstinline+\RequirePackage+ and
+ \lstinline+\RequirePackageWithOptions+, as well as
+ \lstinline+\documentclass+,
+ \lstinline+\LoadClass+ and
+ \lstinline+\LoadClassWithOptions+.
+Their syntax and effective semantics
+are the same as they have always been. Their effects are just delayed,
+reordered and perhaps modified by the active \emph{package loading rules}.
+
+
+
+\subsection {Package Loading Rules} % % % % % % % %
+
+\marginnote{\ttfamily\bfseries\textbackslash Load}\noindent
+Each invocation if the \lstinline+\Load+ command sets up a rule about
+a class, package or packages, which are not necessarily ever loaded.
+These rules can come from any number of different sources.
+A central registry will be maintained together with \lstinline+pkgloader+ itself
+in the form of |pkgloader-recommended.sty|,
+specifying well-known conflicts and resolutions.
+Individual package authors, however, can supply their own rules,
+as can document authors. Though ideally, for the
+average document author, things should `just work'.
+
+The \lstinline+\Load+ command expects the following syntax:
+
+\vskip\abovedisplayskip
+\begingroup
+\centering
+\begin{tabular}{r@{\ \ \ \ }r@{\ \ \ \ }l}
+ \nt{load} &$::=$& \lstinline+\Load+$\ \nt{package}\ \ \nt{clause}_1\ \ldots\ \nt{clause}_i$ \\
+ &$ \|$& \lstinline+\Load class+$\ \nt{package}\ \ \nt{clause}_1\ \ldots\ \nt{clause}_i$ \\
+ &$ \|$& \lstinline+\Load error+ $\ \ \ \,\nt{clause}_1\ \ldots\ \nt{clause}_i$ \\[2mm]
+
+ \nt{package} &$::=$& \lstinline+[+$\;\nt{options}\;$\lstinline+] {+$\;\nt{pkg}\;$\lstinline+} [+$\;\nt{version}\;$\lstinline+]+ \\[2mm]
+
+ \nt{clause} &$::=$& $\nt{order}\ \ \|\ \ \nt{condition}\ \ \|\ \ \nt{reason}$ \\[2mm]
+
+ \nt{order} &$::=$& \lstinline+before {+ $\nt{pkg}_1\,$\lstinline+, +$\ldots\,$\lstinline+, +$\nt{pkg}_j$ \lstinline+}+ \\
+ &$ \|$& \lstinline+after {+ $\nt{pkg}_1\,$\lstinline+, +$\ldots\,$\lstinline+, +$\nt{pkg}_j$ \lstinline+}+ \\
+ &$ \|$& \lstinline+early+ \\
+ &$ \|$& \lstinline+late+ \\[2mm]
+
+ \nt{condition} &$::=$& \lstinline+always+ $\ \ \|\ \ $
+ \lstinline+if loaded+ $\ \ \|\ \ $
+ \lstinline+if {+ $\nt{\phi}$ \lstinline+}+ \\[2mm]
+
+ \nt{\phi} &$::=$& $\nt{pkg}$ $\ \ \|\ \ $
+ $\nt{\phi}\ $\lstinline+&&+$\ \nt{\phi}$ $\ \ \|\ \ $
+ $\nt{\phi}\ $\lstinline+||+$\ \nt{\phi}$ $\ \ \|\ \ $
+ \lstinline+!+$\;\nt{\phi}$ $\ \ \|\ \ $
+ \lstinline+(+$\;\nt{\phi}\;$\lstinline+)+ \\[2mm]
+
+ \nt{reason} &$::=$& \lstinline+because {+ $\nt{token{-}list}$ \lstinline+}+
+\end{tabular}
+\endgroup
+\vskip\belowdisplayskip
+
+\noindent
+\nt{pkg} represents a package or class name.
+\nt{token{-}list} should expand to a human-readable text without formatting.
+
+\marginnote{\ttfamily\bfseries if}\noindent
+The \( \nt{condition} \) clause determines under which package loading
+conditions any and all parts of a rule are invoked.
+Here is an example of the use of the \( \nt{condition} \) clause:
+\begin{latex}
+\Load {res-ie-lst} if {inputenc && listings}
+\Load {fixltx2e} always
+\end{latex}
+
+\lstinline+res-ie-lst+ (a fictional package built specifically to resolve the
+conflict between \lstinline+inputenc+ and \lstinline+listings+) will be loaded if requested
+specifically, or if both \lstinline+inputenc+ and \lstinline+listings+ are loaded. The \lstinline+fixltx2e+ package is
+always loaded, as it was created to smooth over some mistakes in the
+\LaTeXe\ core.
+
+\marginnote{\ttfamily\bfseries always\\ if loaded}
+The \lstinline+always+ keyword makes a rule unconditional. The \lstinline+if loaded+
+directive makes a rule conditional on its package already being loaded anyway.
+This can be used to order two packages only when they are being loaded by other
+means, and is actually the default behavior (in other words, \lstinline+if loaded+
+really does nothing).
+
+\marginnote{\ttfamily\bfseries before\\ after}
+The \lstinline+before+ and \lstinline+after+ keywords should be pretty straightforward. They
+can be used for things like:
+\begin{latex}
+\Load {xltxtra} after {graphicx}
+\end{latex}
+which fixes the loading order between these two packages when they are both loaded.
+
+\marginnote{\ttfamily\bfseries early\\ late}
+But the set of \LaTeX\ packages is constantly growing, and it appears that
+some big packages should almost always be loaded early in the process,
+and others should almost always be loaded late. Therefore the \lstinline+early+
+and \lstinline+late+ stages are provided as a fallback mechanism. If two packages
+are not related by an explicit application order, their loading order
+may still be decided by their relative stages: \lstinline+early+ before `normal' before \lstinline+late+.
+That way, conflicts may be avoided in a majority of cases.
+This is implemented with |pkgloader-early| and |pkgloader-late| stubs in
+the loading order graph.
+
+The following example uses the \( \nt{order} \) clause
+in addition to the \( \nt{condition} \) clause:
+\begin{latex}
+\Load {res-ie-lst} if {inputenc && listings}
+ after {inputenc , listings}
+\Load {fixltx2e} always early
+\end{latex}
+An important observation about the loading order is that it
+might form a cycle when contradictory ordering rules are specified:
+\begin{latex}
+\Load {pkg1} after {pkg2}
+\Load {pkg2} after {pkg1}
+\end{latex}
+In practice this could happen if the authors of \lstinline+pkg1+ and \lstinline+pkg2+
+independently discover a conflict, and both try to solve it by patching
+their code and having their own package be loaded last. \lstinline+pkgloader+
+can provide a clear error message when this happens, allowing the
+two package authors to seek contact and collaborate on a solution.
+
+\marginnote{\ttfamily\bfseries error}
+Now, about the \lstinline+error+ keyword.
+Initially all package combinations are valid. But if two packages
+are irredeemably incompatible, their combination can be made to trigger
+an error message by a command such as the following:
+\begin{latex}
+\Load error if {algorithms && pseudocode}
+\end{latex}
+These two packages provide almost identical functionality and conflict
+on many command-names. It was generally agreed upon that they should
+never be loaded together. Document authors should simply choose one
+or the other.
+
+\marginnote{\ttfamily\bfseries because}
+Finally, the \( \nt{reason} \) clause can be used to supply a
+human-readable explanation of a rule.
+We finish the above examples by providing reasons:
+\begin{latex}[basewidth=.598em]
+\Load {res-ie-lst} if {inputenc && listings}
+ after {inputenc , listings}
+ because {it allows the use of 1 byte unicode
+ characters in code listings}
+
+\Load {fixltx2e} always early
+ because {it fixes some imperfections in LaTeX2e}
+
+\Load error when {algorithms && pseudocode}
+ because {they provide almost identical functionality
+ and conflict on many command names}
+\end{latex}
+In the future, reasons will be extracted automatically to
+generate documentation. For now, they are displayed with error
+messages related to the rule in question.
+
+
+\subsection {Status} % % % % % % % %
+
+So far, \lstinline+pkgloader+ seems to work as expected, but has not
+yet been tested as extensively as it should be. Therefore, bug-reports
+on the |pkgloader| issue tracker on Github would be most welcome.
+Also, lots more recommended package loading rules are needed.
+
+I nonetheless decided to publish the package now, because I've been
+promising to do so for a while now:
+
+\begin{center}
+ \url{http://tex.stackexchange.com/questions/123174}
+\end{center}
+
+\noindent
+I hope that, with feedback and community collaboration,
+use of this package will become widespread and package
+authors will be able to work in a more modular fashion.
+
+\emph{Future versions} of |pkgloader| will be able to
+intelligently merge package options
+and to track packages loaded by other packages in order
+to better inform the user --- perhaps even fix problems
+by carrying information into the next run through auxiliary files.
+But most of this will depend on feedback.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{document} %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%