summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/everyhook
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/everyhook
Initial commit
Diffstat (limited to 'macros/latex/contrib/everyhook')
-rw-r--r--macros/latex/contrib/everyhook/README44
-rw-r--r--macros/latex/contrib/everyhook/everyhook.dtx672
-rw-r--r--macros/latex/contrib/everyhook/everyhook.pdfbin0 -> 115777 bytes
3 files changed, 716 insertions, 0 deletions
diff --git a/macros/latex/contrib/everyhook/README b/macros/latex/contrib/everyhook/README
new file mode 100644
index 0000000000..a282ebedb1
--- /dev/null
+++ b/macros/latex/contrib/everyhook/README
@@ -0,0 +1,44 @@
+$Id: README 13 2014-11-26 16:22:03Z steve $
+
+ABOUT
+
+The everyhook package takes control of the six TeX token parameters
+everypar, everymath, everydisplay, everyhbox, everyvbox, and everycr.
+Real hooks for each of these can be installed using a stack like
+interface. For compatibility with LaTeX standard classes and packages,
+each of the everyX token lists can be set without interfering with the
+hooks.
+
+
+LICENSE
+
+Copyright (C) 2010, 2011, 2014 by Stephen Checkoway
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either
+version 1.3c 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.3c 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 Stephen Checkoway.
+
+This work consists of everyhook.dtx and the derived file
+everyhook.sty.
+
+REQUIREMENTS
+
+- e-TeX
+- etoolbox package
+
+INSTALLATION
+
+1. Unpack the everyhook.tds.zip archive in the root directory of the
+ local TeX installation tree.
+
+2. Update the file name database, if required by running mktexlsr.
diff --git a/macros/latex/contrib/everyhook/everyhook.dtx b/macros/latex/contrib/everyhook/everyhook.dtx
new file mode 100644
index 0000000000..bb62f32b53
--- /dev/null
+++ b/macros/latex/contrib/everyhook/everyhook.dtx
@@ -0,0 +1,672 @@
+% \iffalse The license starting three lines down applies to this file
+%<*batchfile>
+\begingroup\input docstrip \preamble
+Copyright (C) 2010, 2011, 2014 by Stephen Checkoway
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either
+version 1.3c 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.3c 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 Stephen Checkoway.
+
+This work consists of everyhook.dtx and the derived file
+everyhook.sty.
+\endpreamble
+\keepsilent
+\usedir{tex/latex/everyhook}
+\askforoverwritefalse
+\generate{\file{\jobname.sty}{\from{\jobname.dtx}{}}}
+\endgroup
+
+\documentclass{ltxdoc}
+\usepackage{fixltx2e}
+\usepackage{etoolbox}
+\usepackage[osf]{mathpazo}
+\usepackage[scaled=0.86]{berasans}
+\usepackage[scaled=1.03]{inconsolata}
+\usepackage[T1]{fontenc}
+\usepackage{microtype}
+\usepackage[margin=1.5in]{geometry}
+\usepackage[excludeor]{everyhook}
+\usepackage{enumitem}
+\usepackage[pdfborder={0 0 0}]{hyperref}
+\usepackage{ifpdf}
+\usepackage{listings}
+\usepackage{lipsum}
+\begingroup
+\catcode`\^^09\active
+\gdef\obeytabs{%
+\catcode`\^^09\active
+\def^^09{\ \ \ \ \ \ \ \ }%
+}
+\endgroup
+\makeatletter
+\patchcmd\macrocode{\@vobeyspaces}{\@vobeyspaces\obeytabs}{}{\undefined}
+\makeatother
+
+\CheckSum{190}
+\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 \~}
+
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\GetFileInfo{\jobname.sty}
+\title{The \textsf{\jobname} package\thanks{This document
+corresponds to \textsf{\jobname}~\fileversion, dated \filedate.}}
+\author{Stephen Checkoway\\\texttt{s@cs.jhu.edu}}
+
+\lstset{language=[LaTeX]TeX,basicstyle=\ttfamily,
+texcsstyle=*\normalfont\bfseries,
+moretexcs={paragraph,RequirePackage},xleftmargin=\parindent}
+
+\renewcommand*\arg[1]{\textsf{\{#1\}}}
+\makeatletter
+\renewcommand*\meta@font@select{\normalfont\itshape}
+% \DescribeOption taken from trivfloat.dtx
+\newcommand*{\DescribeOption}{%
+ \leavevmode
+ \@bsphack
+ \begingroup
+ \MakePrivateLetters
+ \Describe@Option
+}
+\newcommand*{\Describe@Option}[1]{%
+ \endgroup
+ \marginpar{%
+ \raggedleft
+ \PrintDescribeEnv{#1}%
+ }%
+ \@esphack
+ \ignorespaces
+}
+\makeatother
+\begin{document}
+\maketitle
+
+\begin{abstract}
+The \textsf{\jobname} package takes control of the six \TeX\
+token parameters \cs{everypar}, \cs{everymath}, \cs{everydisplay},
+\cs{everyhbox}, \cs{everyvbox}, and \cs{everycr}. Real hooks for
+each of these can be installed using a stack like interface. For
+compatibility with \LaTeX\ standard classes and packages, each of
+the \cs{everyX} token lists can be set without interfering with the
+hooks.
+\end{abstract}
+\tableofcontents
+
+\section{Introduction}
+\TeX\ contains nine token parameters, seven of which are inserted
+into the current list at various times. Quoting from \textit{The
+\TeX book}, the seven token parameters of interest are\footnote{The remaining two
+token parameters are \cs{output} and \cs{errhelp}.}
+\begin{description}[labelindent=1em, noitemsep]
+\item{\cs{everypar}\enskip} tokens to insert when a paragraph begins,
+\item{\cs{everymath}\enskip} tokens to insert when math in text begins,
+\item{\cs{everydisplay}\enskip} tokens to insert when display math begins,
+\item{\cs{everyhbox}\enskip} tokens to insert when an hbox begins,
+\item{\cs{everyvbox}\enskip} tokens to insert when a vbox begins,
+\item{\cs{everyjob}\enskip} tokens to insert when the job begins, and
+\item{\cs{everycr}\enskip} tokens to insert after every \cs{cr} or
+nonredundant \cs{crcr}.
+\end{description}
+Of these, \cs{everyjob} is not very useful outside of INITEX and so
+it won't be considered further.
+
+The remaining six token parameters can be used to great effect. For
+example, the \cs{everypar} is used in \cs{paragraph} to set the title
+of the paragraph inline allowing constructions like\\
+\indent\hbox to.45\textwidth{%
+\begin{lstlisting}[boxpos=b]
+\paragraph{Paragraph title.}
+
+A blank line followed by
+the rest of the paragraph.
+\end{lstlisting}\hfil
+}
+\hfill
+\parbox[b]{.45\textwidth}{
+\paragraph{Paragraph title.}
+
+\strut A blank line followed by the rest of the paragraph.
+\\[\baselineskip]
+}\\[\baselineskip]
+which work properly rather than starting a new paragraph due to the
+blank line.
+
+Similarly, \cs{everymath} and \cs{everydisplay} are used by the
+\LaTeX\ kernel to set up math fonts.
+
+Using the \TeX\ primitives directly has the major downside that they
+cannot be used by multiple packages at the same time. Setting
+\cs{everypar} overwrites a prior usage. Even if one package is careful
+and always uses
+\begin{lstlisting}
+\everypar=\expandafter{\the\everypar new tokens here}
+\end{lstlisting}
+so as not to stomp on another's usage, there's no guarantee that the
+other package will not later set \lstinline!\everypar={}!.
+
+To get around this, the \textsf{\jobname} package takes control of the
+six \cs{everyX} primitives listed above and for each one provides a
+stack like interface for two additional token lists, one to be
+expanded before the \cs{everyX} and one to be expanded after. For
+example,
+\begin{lstlisting}
+\PushPreHook{hbox}{1}
+\PushPreHook{hbox}{2}
+\everyhbox={3}
+\PushPostHook{hbox}{4}
+\PushPostHook{hbox}{5}
+\end{lstlisting}
+will cause the insertion of the tokens |21345| at the start of an
+\cs{hbox}. Note that \cs{PushPreHook} adds tokens to the \emph{left}
+of the list of tokens to appear before those in \cs{everyhbox} whereas
+\cs{PushPostHook} adds tokens to the \emph{right} of the list of
+tokens to appear after those in \cs{everyhbox}.
+
+\section{Usage}
+The \textsf{\jobname} package has one (rather experimental) option,
+|excludeor| and is loaded using
+\begin{lstlisting}
+\usepackage[excludeor]{everyhook}
+\end{lstlisting}
+or
+\begin{lstlisting}
+\RequirePackage[excludeor]{everyhook}
+\end{lstlisting}
+as required where the option is, of course, optional.
+
+\subsection{Options}
+\DescribeOption{excludeor}
+Some of the hooks described below can cause unwanted behavior when
+active during the execution of \LaTeX's output routine. The
+experimental |excludeor| option saves and clears the hooks at
+the beginning of the output routine and restores them at the end.
+
+\subsection{Manipulating hooks}
+There are 12 hooks, a pre and post hook for each of the six token
+parameters |par|, |math|, |display|, |hbox|, |vbox|, and |cr|. The
+first argument to all of the macros described in this section must be
+one of these six. \textbf{All hook manipulation is \emph{global}.}
+
+\paragraph{Pre hooks.}
+\DescribeMacro{\PushPreHook}
+\DescribeMacro{\PopPreHook}
+Additional tokens \meta{balanced text} are prepended to the pre hook
+\meta{hook} using \cs{PushPreHook}\arg{\meta{hook}}\arg{\meta{balanced
+text}}. The most recently pushed tokens can be popped off using
+\cs{PopPreHook}\arg{\meta{hook}}.
+
+\paragraph{Post hooks.}
+\DescribeMacro{\PushPostHook}
+\DescribeMacro{\PopPostHook}
+Additional tokens \meta{balanced text} are appended to the post hook
+\meta{hook} using
+\cs{PushPostHook}\arg{\meta{hook}}\arg{\meta{balanced text}}. The most
+recently pushed tokens can be popped off using
+\cs{PopPostHook}\arg{\meta{hook}}.
+
+\paragraph{Saving, restoring, and clearing hooks.}
+\DescribeMacro{\SavePreHook}
+\DescribeMacro{\SavePostHook}
+\DescribeMacro{\RestorePreHook}
+\DescribeMacro{\RestorePostHook}
+\DescribeMacro{\ClearPreHook}
+\DescribeMacro{\ClearPostHook}
+Each of the 12 pre and post hooks can be saved to a macro, restored
+from a macro, or cleared independently. To save the pre hook
+\meta{hook} to the macro \cs{cs}, use
+\cs{SavePreHook}\arg{\meta{hook}}\arg{\cs{cs}}. Restoring is
+accomplished by \cs{RestorePreHook}\arg{\meta{hook}}\arg{\cs{cs}}. To
+clear all of the tokens in a pre hook use
+\cs{ClearPreHook}\arg{\meta{hook}}. The \cs{SavePostHook},
+\cs{RestorePostHook}, and \cs{ClearPostHook} are analogous.
+
+\section{Example}
+As a nontrivial example of where this package can be used, consider
+the following example.
+\begin{lstlisting}
+\documentclass{article}
+\usepackage{everyhook}
+\usepackage{lipsum}
+
+\begin{document}
+\setlength{\parindent}{0pt}
+\PushPreHook{par}{\llap{\textbullet\enskip}\null}
+\paragraph{Lorem ipsum.}
+\lipsum[1-4]
+\PopPreHook{par}
+\end{document}
+\end{lstlisting}
+This code will cause each paragraph of the \emph{lorem ipsum} text to
+have no indentation and instead to place a bullet in the margin. See
+Figure~\ref{fig:example}. If \cs{everypar} were used instead, the
+\cs{paragraph} would replace the command to create the bullet with
+those needed to typeset the paragraph title.
+
+\begin{figure}[p]
+\centering
+\fbox{\makebox[.975\textwidth][c]{\parbox{\dimexpr.975\textwidth-1in\relax}{
+\vspace*{\dimexpr .5in-3.25ex}
+\PushPreHook{par}{\llap{\textbullet\enskip}\null}
+\paragraph{Lorem ipsum.}
+\lipsum[1-4]
+\PopPreHook{par}
+
+\vskip.5in
+}}}
+\caption{Example output.}
+\label{fig:example}
+\end{figure}
+
+Note that this package is not a panacea. We had to add a \cs{null} to
+the |par| hook because \cs{paragraph} uses \cs{lastbox} to remove the
+indentation box. Without the \cs{null} it ends up removing the box
+constructed by \cs{llap} instead.
+
+Using the post |par| hook solves the \cs{lastbox} problem, but then
+the bullet is placed to the right of the \cs{paragraph} title.
+
+Perhaps a better way to solve this problem is to remove the
+indentation box first, insert the bullet, and then place the box
+after. In this way, the bullet is always to the left of the
+paragraph indentation.
+\begin{lstlisting}
+\PushPreHook{par}{{\setbox0=\lastbox
+ \llap{\textbullet\enskip}\box0}}
+\end{lstlisting}
+
+\section{Potential pitfalls}
+As noted in the previous section, it can be tricky to use the |par|
+hook correctly. This section contains an (almost certainly) incomplete
+list of pitfalls to watch out for when using \textsf{\jobname}.
+\begin{enumerate}
+\item When using the |par| hooks, be aware that TeX will insert a box
+with the width of \cs{parindent} before the tokens in the pre hook.
+One way to handle this is to propogate the box to the right.
+\item It is probably not a good idea to use the |hbox|, |vbox|, and
+|par| hooks at any place where TeX's output routine is likely to run.
+The |excludeor| option \emph{should} help with this, but it might
+cause problems with other packages that also modify the output
+routine.
+\item \LaTeX's kernel takes control of the \cs{everymath} and
+\cs{everydisplay} token parameters to make its own adjustments in much
+the same way this package does. The \textsf{trace} package uses the
+kernel's private macros to insert its own hooks. It is probably best
+to only use the post |math| and |display| hooks to ensure that the
+kernel has done what it needs to do before you start typesetting stuff
+in math mode.
+\item When using the |hbox| and |vbox| hooks, any hbox or vbox that
+appears in a \cs{setbox} will have the \cs{afterassignment} token
+inserted \emph{before} the hooks. This is no different from TeX's
+normal behavior with \cs{afterassignment} and
+\cs{everyhbox}/\cs{everyvbox}, but can be surprising.
+\item I'm sure there are others.
+\end{enumerate}
+
+\StopEventually{
+ \typeout{**************************************************}
+ \typeout{*}
+ \typeout{* To finish the installation, you have to move the}
+ \typeout{* following file into a directory searched by TeX:}
+ \typeout{*}
+ \typeout{* \space\space \jobname.sty}
+ \typeout{*}
+ \typeout{* Documentation is in \jobname.\ifpdf pdf\else dvi\fi.}
+ \typeout{*}
+ \typeout{* Happy TeXing!}
+ \typeout{**************************************************}
+ \end{document}
+}
+
+\clearpage
+\DocInput{\jobname.dtx}
+\clearpage
+\phantomsection
+\addcontentsline{toc}{section}{Change History}%
+\PrintChanges
+\phantomsection
+\addcontentsline{toc}{section}{Index}%
+\PrintIndex
+\Finale
+%</batchfile>
+% \fi
+% \DoNotIndex{\csdef,\cslet,\csname,\csuse,\def,\endcsname,\endinput,
+% \every,\expandafter,\gdef,\global,\ifcsdef,\ifcsempty,\ifdefequal,
+% \letcs,\newrobustcmd,\newtoks,\PackageError,\protect,\RequirePackage,
+% \space,\the,\undef}
+%
+% \section{Implementation}
+% The package begins with the usual package identification and then it
+% declares the one option |excludeor| and finally it loads the
+% \textsf{etoolbox} package. This package is not strictly necessary,
+% but it does simplify some stuff and provides handy macros for
+% dealing with control sequence names.
+%
+% \changes{v1.0}{2010/09/26}{Initial version}
+% \changes{v1.1}{2011/02/03}{Add excludeor}
+% \changes{v1.2}{2014/11/26}{Let everyX be redefined}
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+\RequirePackage{svn-prov}
+\ProvidesPackageSVN
+ {$Id: everyhook.dtx 12 2014-11-26 15:34:56Z steve $}
+ [v1.2 \revinfo\ Hooks for low level TeX everyX primitives.]
+\DeclareOption{excludeor}{%
+ \AtBeginDocument{%
+ \output\expandafter{%
+ \expandafter\eh@saveclearallhooks
+ \the\output
+ \eh@restoreallhooks
+ }%
+ }%
+}
+\ProcessOptions\relax
+\RequirePackage{etoolbox}
+% \end{macrocode}
+%
+% \begin{macro}{\eh@definehook}
+% This performs all of the setup work for each hook. First, it takes
+% control of \TeX's token parameter given in the second argument. Then
+% it shadows the name of the primitive with a normal token register (and
+% copies the current definition). The pre and post hooks are defined
+% to be initially empty.
+% \begin{macrocode}
+\def\eh@definehook#1#2{%
+ \cslet{eh@every#1}#2%
+ \newtoks#2%
+ \cslet{eh@private#1}#2%
+ #2\csuse{eh@every#1}%
+ \csdef{eh@pre#1}{}%
+ \csdef{eh@post#1}{}%
+% \end{macrocode}
+% This is slightly tricky to get right. Basically, we want to set the
+% \cs{everyfoo} primitive which we have saved as \cs{eh@everyfoo}
+% like
+%
+% \indent\lstinline!\eh@everyfoo={\eh@prefoo\the\expandafter\everyfoo\eh@postfoo}!.
+%
+% The reason for the \cs{expandafter} is to make sure it is expanded
+% before the the token register \cs{everyfoo} is expanded. Thus if the
+% post hook is empty, then code in \cs{everyfoo} sees no additional
+% tokens, in case that is important.
+%
+% Unfortunately, some code wants to redefine \cs{everyfoo} itself in
+% order to prevent \emph{other} code that uses \cs{everyfoo} from
+% actually setting anything. To deal with that, we use the private
+% token list
+%
+% \indent\lstinline!\eh@everyfoo{\eh@prefoo\the\expandafter\eh@privatefoo\eh@postfoo}!
+% \begin{macrocode}
+ \csuse{eh@every#1}\expandafter{\csname eh@pre#1\expandafter\endcsname
+ \expandafter\the\csname eh@private#1\expandafter\endcsname
+ \csname eh@post#1\endcsname}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\everypar}
+% Define the hooks for the |par| hook.
+% \begin{macrocode}
+\eh@definehook{par}\everypar
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\frozen@everymath}
+% \begin{macro}{\frozen@everydisplay}
+% Define the |math| and |display| hooks. Since the \LaTeX\ kernel has
+% already saved \cs{everymath} and \cs{everydisplay} into the frozen
+% macros, we take control by redefining the frozen ones instead.
+% \begin{macrocode}
+\eh@definehook{math}\frozen@everymath
+\eh@definehook{display}\frozen@everydisplay
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\everyhbox}
+% \begin{macro}{\everyvbox}
+% \begin{macro}{\everycr}
+% Define the |hbox|, |vbox|, and |cr| hooks and free up some used
+% memory.
+% \begin{macrocode}
+\eh@definehook{hbox}\everyhbox
+\eh@definehook{vbox}\everyvbox
+\eh@definehook{cr}\everycr
+\undef\eh@definehook
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\eh@hookseparator}
+% An separator used to separate tokens in each hook.
+% \begin{macrocode}
+\def\eh@hookseparator{}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\eh@checkhook}
+% Check that the hook is one of the six.
+% \begin{macrocode}
+\def\eh@checkhook#1#2{%
+ \ifcsdef{eh@every#1}{}{\PackageError{everyhook}{Argument #1 to
+ \protect#2\space is invalid}{There is no hook for
+ \protect\every#1.}}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\eh@checkhooknotempty}
+% Check that the hook is both defined and not empty so that we can
+% pop.
+% \begin{macrocode}
+\def\eh@checkhooknotempty#1#2#3{%
+ \eh@checkhook{#2}#3%
+ \ifcsempty{eh@#1#2}{\PackageError{everyhook}{The #1 hook for
+ \protect\every#2\space is empty}{I have seen too many
+ \protect#3{#2}s.}{}}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\PushPreHook}
+% Prepend tokens to the pre hook, separated via the separator.
+% \begin{macrocode}
+\newrobustcmd\PushPreHook[2]{%
+ \eh@checkhook{#1}\PushPreHook
+ \def\eh@tempi{#2}%
+ \letcs\eh@tempii{eh@pre#1}%
+ \expandafter\gdef\csname eh@pre#1\expandafter\expandafter
+ \expandafter\endcsname\expandafter\expandafter
+ \expandafter{\expandafter\eh@tempi\expandafter
+ \eh@hookseparator\eh@tempii}%
+ \undef\eh@tempi
+ \undef\eh@tempii
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\PopPreHook}
+% \begin{macro}{\eh@popprehook}
+% Check that the hook is not empty, and then pop off the left tokens
+% and separator. We can use delimited parameters to strip off the
+% first set of tokens.
+% \begin{macrocode}
+\newrobustcmd\PopPreHook[1]{%
+ \eh@checkhooknotempty{pre}{#1}\PopPreHook
+ \expandafter\eh@popprehook\csname eh@pre#1\expandafter
+ \expandafter\expandafter\endcsname
+ \csname eh@pre#1\endcsname\eh@hookend
+}
+\def\eh@popprehook#1#2\eh@hookseparator#3\eh@hookend{\gdef#1{#3}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\PushPostHook}
+% Append a separator and tokens to the post hook.
+% \begin{macrocode}
+\newrobustcmd\PushPostHook[2]{%
+ \eh@checkhook{#1}\PushPostHook
+ \letcs\eh@tempi{eh@post#1}%
+ \expandafter\gdef\csname eh@post#1\expandafter\endcsname
+ \expandafter{\eh@tempi\eh@hookseparator#2}%
+ \undef\eh@tempi
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\PopPostHook}
+% \begin{macro}{\eh@popposthook}
+% \begin{macro}{\eh@sentinel}
+% Check that the post hook is not empty. Then, iterate over the tokens
+% in the list until we reach the end and strip that off.
+% \begin{macrocode}
+\newrobustcmd\PopPostHook[1]{%
+ \eh@checkhooknotempty{post}{#1}\PopPostHook
+ \letcs\eh@tempi{eh@post#1}%
+ \expandafter\eh@popposthook\csname eh@post#1\expandafter
+ \endcsname\expandafter{\expandafter}\eh@tempi
+ \eh@hookend\eh@hookseparator\eh@sentinel\eh@hookend
+ \undef\eh@tempi
+}
+\def\eh@popposthook#1#2\eh@hookseparator#3\eh@hookseparator#4\eh@hookend{%
+ \def\eh@tempi{#4}%
+ \ifdefequal\eh@sentinel\eh@tempi%
+ {\gdef#1{#2}\undef\eh@tempi}%
+ {\eh@popposthook#1{#2\eh@hookseparator#3}\eh@hookseparator#4\eh@hookend}%
+}
+\def\eh@sentinel{\eh@sentinel}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\eh@clearhook}
+% Internal hook reset.
+% \begin{macrocode}
+\def\eh@clearhook#1{%
+ \global\csdef{eh@#1}{}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\ClearPreHook}
+% \begin{macro}{\ClearPostHook}
+% Reset the pre/post hook to empty.
+% \begin{macrocode}
+\newrobustcmd\ClearPreHook[1]{%
+ \eh@checkhook{#1}\ClearPreHook
+ \eh@clearhook{pre#1}%
+}
+\newrobustcmd\ClearPostHook[1]{%
+ \eh@checkhook{#1}\ClearPostHook
+ \eh@clearhook{post#1}%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\eh@savehook}
+% \begin{macro}{\eh@restorehook}
+% Internal macros to \cs{let} the hook to the supplied control
+% sequence to save. Perform the \cs{let} in the other direction to
+% restore.
+% \begin{macrocode}
+\def\eh@savehook#1#2{%
+ \letcs#2{eh@#1}%
+}
+\def\eh@restorehook#1#2{%
+ \global\cslet{eh@#1}#2%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\SavePreHook}
+% \begin{macro}{\SavePostHook}
+% \begin{macro}{\RestorePreHook}
+% \begin{macro}{\RestorePostHook}
+% User macros to save and restore hooks.
+% \begin{macrocode}
+\newrobustcmd\SavePreHook[2]{%
+ \eh@checkhook{#1}\SavePreHook
+ \eh@savehook{pre#1}#2%
+}
+\newrobustcmd\SavePostHook[2]{%
+ \eh@checkhook{#1}\SavePostHook
+ \eh@savehook{post#1}#2%
+}
+\newrobustcmd\RestorePreHook[2]{%
+ \eh@checkhook{#1}\RestorePreHook
+ \eh@restorehook{pre#1}#2%
+}
+\newrobustcmd\RestorePostHook[2]{%
+ \eh@checkhook{#1}\RestorePostHook
+ \eh@restorehook{post#1}#2%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\eh@saveclearallhooks}
+% \begin{macro}{\eh@restoreallhooks}
+% Internal macros to save and clear (resp.\ restore) all hooks at the
+% start (resp.\ end) of the output routine.
+% \begin{macrocode}
+\def\eh@saveclearallhooks{%
+ \global\eh@savehook{prepar}\eh@or@prepar
+ \global\eh@savehook{postpar}\eh@or@postpar
+ \global\eh@savehook{premath}\eh@or@premath
+ \global\eh@savehook{postmath}\eh@or@postmath
+ \global\eh@savehook{predisplay}\eh@or@predisplay
+ \global\eh@savehook{postdisplay}\eh@or@postdisplay
+ \global\eh@savehook{prehbox}\eh@or@prehbox
+ \global\eh@savehook{posthbox}\eh@or@posthbox
+ \global\eh@savehook{prevbox}\eh@or@prevbox
+ \global\eh@savehook{postvbox}\eh@or@postvbox
+ \global\eh@savehook{precr}\eh@or@precr
+ \global\eh@savehook{postcr}\eh@or@postcr
+ \eh@clearhook{prepar}%
+ \eh@clearhook{postpar}%
+ \eh@clearhook{premath}%
+ \eh@clearhook{postmath}%
+ \eh@clearhook{predisplay}%
+ \eh@clearhook{postdisplay}%
+ \eh@clearhook{prehbox}%
+ \eh@clearhook{posthbox}%
+ \eh@clearhook{prevbox}%
+ \eh@clearhook{postvbox}%
+ \eh@clearhook{precr}%
+ \eh@clearhook{postcr}%
+}
+\def\eh@restoreallhooks{%
+ \eh@restorehook{prepar}\eh@or@prepar
+ \eh@restorehook{postpar}\eh@or@postpar
+ \eh@restorehook{premath}\eh@or@premath
+ \eh@restorehook{postmath}\eh@or@postmath
+ \eh@restorehook{predisplay}\eh@or@predisplay
+ \eh@restorehook{postdisplay}\eh@or@postdisplay
+ \eh@restorehook{prehbox}\eh@or@prehbox
+ \eh@restorehook{posthbox}\eh@or@posthbox
+ \eh@restorehook{prevbox}\eh@or@prevbox
+ \eh@restorehook{postvbox}\eh@or@postvbox
+ \eh@restorehook{precr}\eh@or@precr
+ \eh@restorehook{postcr}\eh@or@postcr
+}
+\endinput
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+\endinput
diff --git a/macros/latex/contrib/everyhook/everyhook.pdf b/macros/latex/contrib/everyhook/everyhook.pdf
new file mode 100644
index 0000000000..0eae6be679
--- /dev/null
+++ b/macros/latex/contrib/everyhook/everyhook.pdf
Binary files differ