diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/pkgloader/pkgloader.tex |
Initial commit
Diffstat (limited to 'macros/latex/contrib/pkgloader/pkgloader.tex')
-rw-r--r-- | macros/latex/contrib/pkgloader/pkgloader.tex | 386 |
1 files changed, 386 insertions, 0 deletions
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} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |