stevecheckoway / everyhook Goto Github PK
View Code? Open in Web Editor NEWThe everyhook package provides hooks to TeX's everyX set of token parameters.
The everyhook package provides hooks to TeX's everyX set of token parameters.
Dear Mr Checkoway,
some months ago at the TeX-LaTeX StackExchange forum a question was asked under the title "Macro only to be defined in math mode", https://tex.stackexchange.com/questions/477280/macro-only-to-be-defined-in-math-mode.
The questioner intended to use the everyhook-package for redefining macros that process arguments whenever \everymath
gets carried out.
The question at the TeX-LaTeX StackExchange Forum caused me to look at the code of the everyhook package.
Seems there are some problems with your package
everyhook 2014/11/26 v1.2 (SVN Rev: 12)\ Hooks for low level TeX everyX primitives.
Quote from the documentation (everyhook.pdf):
17 \def\eh@definehook#1#2{%
18 \cslet{eh@every#1}#2%
19 \newtoks#2%
20 \cslet{eh@private#1}#2%
21 #2\csuse{eh@every#1}%
22 \csdef{eh@pre#1}{}%
23 \csdef{eh@post#1}{}%
This is slightly tricky to get right. Basically, we want to set the
\everyfoo primitive which we have saved as \eh@everyfoo like
\eh@everyfoo={\eh@prefoo\the\expandafter\everyfoo\eh@postfoo}.
The reason for the \expandafter is to make sure it is expanded
before the the token register \everyfoo is expanded. Thus if the
post hook is empty, then code in \everyfoo sees no additional
tokens, in case that is important.
Unfortunately, some code wants to redefine \everyfoo itself
in order to prevent other code that uses \everyfoo from actually
setting anything. To deal with that, we use the private
token list
\eh@everyfoo{\eh@prefoo\the\expandafter\eh@privatefoo\eh@postfoo}
24 \csuse{eh@every#1}\expandafter{\csname eh@pre#1\expandafter\endcsname
25 \expandafter\the\csname eh@private#1\expandafter\endcsname
26 \csname eh@post#1\endcsname}%
27 }
A token \expandafter
is promised for ensuring that the macro \eh@post⟨foo⟩
gets expanded before \the\eh@private⟨foo⟩
.
The problem with the code in lines 24-27 is:
That code does not set the token register \eh@every⟨foo⟩
to
\eh@pre⟨foo⟩\the\expandafter\eh@private⟨foo⟩\eh@post⟨foo⟩
but it does set that register to:
\eh@pre⟨foo⟩\the\eh@private⟨foo⟩\eh@post⟨foo⟩
The promised \expandafter
behind \the
is missing.
You can easily test this with the following MWE:
\documentclass{article}
\usepackage{everyhook}
\makeatletter
\showthe\eh@everypar
\stop
Here \showthe\eh@everypar
reveals:
\eh@prepar \the \eh@privatepar \eh@postpar .
l.4 \showthe\eh@everypar
As you can see: The promised \expandafter
behind \the
is missing.
In order to fulfill the promise/in order to have that \expandafter
behind \the
, two \expandafter
need to be added to line 25:
17 \def\eh@definehook#1#2{%
18 \cslet{eh@every#1}#2%
19 \newtoks#2%
20 \cslet{eh@private#1}#2%
21 #2\csuse{eh@every#1}%
22 \csdef{eh@pre#1}{}%
23 \csdef{eh@post#1}{}%
[...]
24 \csuse{eh@every#1}\expandafter{\csname eh@pre#1\expandafter\endcsname
25 \expandafter\the\expandafter\expandafter\csname eh@private#1\expandafter\endcsname %<--------
26 \csname eh@post#1\endcsname}%
27 }
Additionally to fulfilling the promise I'd probably add yet another two \expandafter
to make sure everything is expanded when it comes to carrying out the very first token that comes from \eh@pre⟨foo⟩
:
17 \def\eh@definehook#1#2{%
18 \cslet{eh@every#1}#2%
19 \newtoks#2%
20 \cslet{eh@private#1}#2%
21 #2\csuse{eh@every#1}%
22 \csdef{eh@pre#1}{}%
23 \csdef{eh@post#1}{}%
[...]
24 \csuse{eh@every#1}\expandafter{\expandafter\expandafter\csname eh@pre#1\expandafter\endcsname %<--------
25 \expandafter\the\expandafter\expandafter\csname eh@private#1\expandafter\endcsname %<--------
26 \csname eh@post#1\endcsname}%
27 }
This way \eh@pre⟨foo⟩
gets expanded when \the\eh@private⟨foo⟩
is already expanded while \the\eh@private⟨foo⟩
gets expanded when \eh@post⟨foo⟩
is already expanded.
So this will set the token register \eh@every⟨foo⟩
to
\expandafter\eh@pre⟨foo⟩\the\expandafter\eh@private⟨foo⟩\eh@post⟨foo⟩
Seems a pair of empty braces is not in the right place with \eh@checkhooknotempty
:
Definition of \eh@checkhooknotempty
as found in everyhook.sty v1.2, dated 2014/11/26:
41 \def\eh@checkhooknotempty#1#2#3{%
42 \eh@checkhook{#2}#3%
43 \ifcsempty{eh@#1#2}{\PackageError{everyhook}{The #1 hook for
44 \protect\every#2\space is empty}{I have seen too many
45 \protect#3{#2}s.}{}}%
46 }
\PackageError
takes three arguments. In \eh@checkhooknotempty
four arguments are passed to it. The last one of them is empty.
\ifcsempty
takes three arguments. In \eh@checkhooknotempty
only two arguments are passed to it.
Thus \ifcsempty
's third argument will be taken from the token-stream/input-stream.
In case of the hook not being empty this may probably not matter as in this case the tokens which form that argument will be returned to the token-stream. "probably" because a pair of matching curly braces surrounding that argument will be removed after returning if previously present. This might make a difference.
In case of the hook being empty the tokens forming that argument will not be returned to the token-stream. The effect of the removal of these tokens is not predictable. In harmless cases this just leads to subsequent error-messages which are confusing.
Let's change the line-wrapping:
\def\eh@checkhooknotempty#1#2#3{%
\eh@checkhook{#2}#3%
\ifcsempty{% <- first argument of \ifcsempty
eh@#1#2%
}{% <- second argument of \ifcsempty
\PackageError{% <- first argument of \PackageError
everyhook%
}{% <- second argument of \PackageError
The #1 hook for \protect\every#2\space is empty%
}{% <- third argument of \PackageError
I have seen too many \protect#3{#2}s.%
}{}% <- empty fourth argument of \PackageError ??????????
}% <- where is the third argument of \ifcsempty???????
}%
I suggest something like:
\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.}}{}%<- brace pair "moved"
}%
You can use \PushPreHook
/ \PopPreHook
for adding tokens to / for removing tokens from the definitions of macros \eh@pre⟨foo⟩
.
You can use \PushPostHook
/ \PopPostHook
for adding tokens to / for removing tokens from the definitions of macros \eh@post⟨foo⟩
.
The problem is:
Somebody may add macro-definitions to \eh@pre⟨foo⟩
/ \eh@post⟨foo⟩
.
If this is done, then every subsequent use of
\PushPreHook{⟨foo⟩}...
or \PopPreHook{⟨foo⟩}...
respective
\PushPostHook{⟨foo⟩}...
or \PopPostHook{⟨foo⟩}...
will reduce the amount of hashes / the parameter-characters #
that belong to these definitions.
You can easily test with the following MWE:
\documentclass{article}
\usepackage{everyhook}
\makeatletter
\PushPreHook{par}{D\def\dummy################1{This is the argument ################1}}
\show\eh@prepar
\PushPreHook{par}{C}
\show\eh@prepar
\PushPreHook{par}{B}
\show\eh@prepar
\PushPreHook{par}{A}
\show\eh@prepar
\stop
I'd expect this to yield in the end:
> \eh@prepar=macro:
->A\eh@hookseparator B\eh@hookseparator C\eh@hookseparator D\def \dummy #######
#########################1{This is the argument ###############################
#1}\eh@hookseparator .
The hashes within \eh@prepar
's definition should be doubled because at the time of expanding \eh@prepar
, the amount of hashes will be reduced/halved.
Instead \show
reveals that the amount of hashes gets halved with each use
of \PushPreHook
:
?
> \eh@prepar=macro:
->D\def \dummy ########1{This is the argument ########1}\eh@hookseparator .
l.5 \show\eh@prepar
?
> \eh@prepar=macro:
->C\eh@hookseparator D\def \dummy ####1{This is the argument ####1}\eh@hooksepa
rator .
l.7 \show\eh@prepar
?
> \eh@prepar=macro:
->B\eh@hookseparator C\eh@hookseparator D\def \dummy ##1{This is the argument #
#1}\eh@hookseparator .
l.9 \show\eh@prepar
?
! Illegal parameter number in definition of \eh@prepar.
<to be read again>
1
l.11 \PushPreHook{par}{A}
?
! Illegal parameter number in definition of \eh@prepar.
<to be read again>
1
l.11 \PushPreHook{par}{A}
?
> \eh@prepar=macro:
->A\eh@hookseparator B\eh@hookseparator C\eh@hookseparator D\def \dummy ##1{Thi
s is the argument ##1}\eh@hookseparator .
l.11 \show\eh@prepar
In the end you get error-messages because hashes are reduced so much that remaining hashes are taken for a means of denoting arguments of \eh@prepar
which were not declared in \eh@prepar
's parameter text.
The same situation with \PopPreHook
, \PushPostHook
and \PopPostHook
.
In order to resolve this issue, it is helpful to keep in mind:
Macro-definitions can have ⟨parameter text⟩
and must have ⟨balanced text⟩
.
( ⟨definition⟩ → ⟨def⟩⟨control sequence⟩⟨definition text⟩
⟨def⟩ → \def | \gdef | \edef | \xdef
⟨definition text⟩ → ⟨parameter text⟩⟨left brace⟩⟨balanced text⟩⟨right brace⟩
)
When placing hashes/parameter-characters into a⟨balanced text⟩
that belongs to the ⟨definition text⟩
of the ⟨definition⟩
of a macro, two consecutive hashes of that ⟨balanced text⟩
will be collapsed into one single hash at the time of having expanded the macro in question.
(That's why you can use ##1
/ ##2
etc for the parameters with macro-definitions nested inside the ⟨balanced text⟩
of macro-definitions.)
In short:
Macro expansion will reduce/halve the amount of consecutive hashes that come from the macro's definition's ⟨balanced text⟩
.
When during macro expansion (La)TeX gathers an argument for a macro whereby that argument itself contains hashes, (La)TeX leaves the amount of these hashes untouched.
When (La)TeX encounters hashes while gathering the tokens of a ⟨balanced text⟩
that belongs to ⟨general text⟩
, e.g., the ⟨balanced text⟩
of an assignment to a token-register, it will leave the amount of hashes contained in that ⟨balanced text⟩
untouched: \the⟨token register⟩
under normal circumstances will yield the same amount of hashes as were contained in that ⟨balanced text⟩
.
( ⟨variable assignment⟩ → ... | ⟨token variable⟩⟨equals⟩⟨general text⟩
⟨token variable⟩ → ⟨token parameter⟩ | ⟨toksdef token⟩ | \toks⟨8-bit number⟩
⟨general text⟩ → ⟨filler⟩{⟨balanced text⟩⟨right brace⟩
)
There are special circumstances when hashes will be doubled:
\message{This is my message: #}
yields on the screen: This is my message: ##
.\show
and \message{\meaning\...}
you don't get this hash-doubling. The reason is: At the time of writing to screen \show
and \message
actually don't deal with hash-tokens of category-code 6 (parameter) but with the "stringified" variants thereof, i.e., with hash-tokens of category code 12(other).\detokenize
is like unexpanded-immediate-writing tokens to an external file (hereby hash-dobling takes place!) and reading back that external file under a category-code-régime where everything but space (which has category code 10(space)) has category code 12(other).\scantokens
is like unexpanded-immediate-writing tokens to an external file (hereby hash-dobling takes place!) and reading back that external file under the current category-code-régime.\the
delivers tokens of a ⟨token variable⟩
, e.g., of a token-register or of a token-parameter like \everypar
or \everyeof
during an \edef
/\xdef
-expansion-context, hashes will be doubled.\unexpanded
delivers its ⟨balanced text⟩
during an \edef
/\xdef
-expansion-context, hashes will be doubled. This hash-doubling is done for compensating the circumstance that hashes will be reduced after having expanded the macro in question.\romannumeral0
-expansion is a powerful tool for reducing the amount of \expandafter
needed for triggering desired expansion-steps:
\romannumeral
triggers expansion until (La)TeX finds a number. In the not so interesting case of the number found being positive, (La)TeX will deliver its representation in lowercase roman numerals. In the more interesting case of the number found being not positive, (La)TeX will silently not deliver any token at all but swallow the tokens that form the number.
Therefore \romannumeral
can be (ab?)used for triggering a lot of expansion-work as long as in the end the first tokens from the expansion-result form a non-positive number.
In order to get the sequence \relax6 5 4 3 2 1 0
from macros
\def\top{\first0 }
\def\first{\second1 }
\def\second{\third2 }
\def\third{\fourth3 }
\def\fourth{\fifth4 }
\def\fifth{\sixth5 }
\def\sixth{6 }
you could place (27-1) = 127\expandafter
-tokens in front of the sequence \relax\top
.
If you change the definition of \sixth
to \def\sixth{ 6 }
, you can do:
\expandafter\relax\romannumeral0\top
You get:
%\expandafter-expansion in progress
\relax\romannumeral0\top
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0\top
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0\first0
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0\second1 0
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0\third2 1 0
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0\fourth3 2 1 0
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0\fifth4 3 2 1 0
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0\sixth5 4 3 2 1 0
→
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion in progress
0 6 5 4 3 2 1 0
→ now digit 0
trailed by a space which terminates the digit-sequence that is to be converted is found during searching the number that is to be converted due to \romannumeral
.
The terminating space is discarded. 0 is not a positive number. The tokens that form that number get swallowed silently while no tokens will be delivered:
%\expandafter-expansion in progress
\relax
%\romannumeral-expansion done
6 5 4 3 2 1 0
→ as \romannumeral
-expansion is done, \expandafter
-expansion is done also:
%\expandafter-expansion done
\relax
%\romannumeral-expansion done
6 5 4 3 2 1 0
\romannumeral0
-expansion is very useful in combination with exchanging macro-arguments.
Armed with this knowledge, let's look at the definitions of the macros \PushPreHook
, \PopPreHook
, \PushPostHook
and \PopPostHook
:
Definition of \PushPreHook
as found in everyhook.sty v1.2, dated 2014/11/26:
47 \newrobustcmd\PushPreHook[2]{%
48 \eh@checkhook{#1}\PushPreHook
49 \def\eh@tempi{#2}%
50 \letcs\eh@tempii{eh@pre#1}%
51 \expandafter\gdef\csname eh@pre#1\expandafter\expandafter
52 \expandafter\endcsname\expandafter\expandafter
53 \expandafter{\expandafter\eh@tempi\expandafter
54 \eh@hookseparator\eh@tempii}%
55 \undef\eh@tempi
56 \undef\eh@tempii
57 }
\PushPreHook's
second argument become the ⟨balenced text⟩
of the definition of the temporary macro \eh@tempi
.\expandafter
-chain both that macro \eh@tempi
and the macro \eh@tempii
(which at that time due to \letcs
is equal to \eh@pre⟨foo⟩
) get expanded while no means are applied for ensuring that the reducing of hashes hereby will be compensated.I suggest something like this:
[...]
%%======================================================================
% Helper-macros for \PushPreHook, \PopPreHook, \PushPostHook and \PopPostHook:
%%======================================================================
\newcommand\eh@exchange[2]{#2#1}%
% As everyhook requires etoolbox you are urged to run with eTeX-extensions
% being available.
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \eh@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%% A variant requiring e-TeX extensions:
\newcommand\eh@CheckWhetherNull[1]{%
\romannumeral0\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\@firstoftwo{\expandafter}{} \@firstoftwo}%
{\@firstoftwo{\expandafter}{} \@secondoftwo}%
}%
%%
%% A variant not requiring e-TeX extensions:
%% ( The gist of this macro comes from Robert R. Schneck's
%% \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%% )
%\newcommand\eh@CheckWhetherNull[1]{%
% \romannumeral0\expandafter\@secondoftwo\string{\expandafter
% \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
% \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
% \@secondoftwo\string}\@firstoftwo\expandafter{} %
% \@secondoftwo}{\@firstoftwo\expandafter{} \@firstoftwo}%
%}%
%%-----------------------------------------------------------------------------
%% Check whether argument contains no token \eh@hookseparator which is not
%% nested in braces:
%%.............................................................................
%% \eh@CheckWhetherNoEh@hookseparator{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% contains no exclamation mark>}%
%% {<Tokens to be delivered in case that argument
%% contains exclamation mark>}%
%%
\@ifdefinable\eh@GobbleToEh@hookseparator{%
\long\def\eh@GobbleToEh@hookseparator#1\eh@hookseparator{}%
}%
\newcommand\eh@CheckWhetherNoEh@hookseparator[1]{%
\expandafter\eh@CheckWhetherNull
\expandafter{\eh@GobbleToEh@hookseparator#1\eh@hookseparator}%
}%
%%----------------------------------------------------------------------
%% Use tokens as definition-text of macro without losing
%% # (hashes) during macro-expansion:
%%......................................................................
%% \eh@csxdefunexpanded{<tokens>}%
%% {<name of macro that is to expand to <tokens>;
%% hashes doubled so that they can losslessly be reduced
%% during expansion of the macro>}
% With e-TeX-extensions:
\newcommand\eh@csxdefunexpanded[2]{%
\csxdef{#2}{\unexpanded{#1}}%
}%
% Without e-TeX-extensions:
%\newtoks\eh@scratchtoks\global\eh@scratchtoks{}%
%\newcommand\eh@csxdefunexpanded[2]{%
% \eh@scratchtoks{#1}%
% \csxdef{#2}{\the\eh@scratchtoks}%
% \eh@scratchtoks{}%
%}%
%%----------------------------------------------------------------------
% Checking the availability of e-TeX-extensions could be implemented as follows:
%%......................................................................
%\begingroup
%\edef\eh@tempi{\string\eTeXversion}%
%\edef\eh@tempii{\meaning\eTeXversion}%
%\expandafter\endgroup
%\ifx\eh@tempi\eh@tempii
% % e-TeX extensions are available
%\else
% % e-TeX extensions are not available
%\fi
[...]
%%======================================================================
%% \PushPreHook
%%======================================================================
\newrobustcmd\PushPreHook[2]{%
\eh@checkhook{#1}\PushPreHook
\expandafter\eh@csxdefunexpanded\expandafter{%
\romannumeral0%
\expandafter\expandafter
\expandafter \eh@exchange
\expandafter\expandafter
\expandafter {%
\csname eh@pre#1\endcsname}{ #2\eh@hookseparator}%
}{eh@pre#1}%
}%
Definition of \PopPreHook
as found in everyhook.sty v1.2, dated 2014/11/26:
58 \newrobustcmd\PopPreHook[1]{%
59 \eh@checkhooknotempty{pre}{#1}\PopPreHook
60 \expandafter\eh@popprehook\csname eh@pre#1\expandafter
61 \expandafter\expandafter\endcsname
62 \csname eh@pre#1\endcsname\eh@hookend
63 }
64 \def\eh@popprehook#1#2\eh@hookseparator#3\eh@hookend{\gdef#1{#3}}
Besides the hash-reduction-problem \eh@popprehook
might—in case of the list of \eh@hookseparator
-separated elements stored in \eh@pre⟨foo⟩
having only two elements—remove surrounding braces from the second/remaining element.
I suggest something like this which does not have the hash-reduction problem and which does without returning whatsoever delimited arguments so that brace removal with delimited arguments does does not matter:
\newrobustcmd\PopPreHook[1]{%
\eh@checkhooknotempty{pre}{#1}\PopPreHook
\ifcsdef{eh@pre#1}{%
\expandafter\expandafter\expandafter\eh@CheckWhetherNoEh@hookseparator
\expandafter\expandafter\expandafter{\csname eh@pre#1\endcsname}{}{%
\expandafter\eh@csxdefunexpanded\expandafter{%
\romannumeral0%
\expandafter\expandafter\expandafter\eh@popprehook
\csname eh@pre#1\endcsname
}{eh@pre#1}%
}%
}{}%
}%
\@ifdefinable\eh@popprehook{%
\long\def\eh@popprehook#1\eh@hookseparator{ }%<-this spece will terminate \romannumeral0-expansion.
}%
Definition of \PushPostHook
as found in everyhook.sty v1.2, dated 2014/11/26:
65 \newrobustcmd\PushPostHook[2]{%
66 \eh@checkhook{#1}\PushPostHook
67 \letcs\eh@tempi{eh@post#1}%
68 \expandafter\gdef\csname eh@post#1\expandafter\endcsname
69 \expandafter{\eh@tempi\eh@hookseparator#2}%
70 \undef\eh@tempi
71 }
I suggest something like this:
\newrobustcmd\PushPostHook[2]{%
\eh@checkhook{#1}\PushPostHook
\expandafter\expandafter\expandafter\eh@csxdefunexpanded
\expandafter\expandafter\expandafter{%
\csname eh@post#1\endcsname\eh@hookseparator#2%
}{eh@post#1}%
}%
Definition of \PopPostHook
as found in everyhook.sty v1.2, dated 2014/11/26:
72 \newrobustcmd\PopPostHook[1]{%
73 \eh@checkhooknotempty{post}{#1}\PopPostHook
74 \letcs\eh@tempi{eh@post#1}%
75 \expandafter\eh@popposthook\csname eh@post#1\expandafter
76 \endcsname\expandafter{\expandafter}\eh@tempi
77 \eh@hookend\eh@hookseparator\eh@sentinel\eh@hookend
78 \undef\eh@tempi
79 }
80 \def\eh@popposthook#1#2\eh@hookseparator#3\eh@hookseparator#4\eh@hookend{%
81 \def\eh@tempi{#4}%
82 \ifdefequal\eh@sentinel\eh@tempi%
83 {\gdef#1{#2}\undef\eh@tempi}%
84 {\eh@popposthook#1{#2\eh@hookseparator#3}\eh@hookseparator#4\eh@hookend}%
85 }
86 \def\eh@sentinel{\eh@sentinel}
Besides the hash-reduction-problem the \eh@popposthook
-loop might remove surrounding braces with all elements of the list of \eh@hookseparator
-separated elements stored in \eh@post⟨name of hook⟩
.
I suggest something like this:
\newrobustcmd\PopPostHook[1]{%
\eh@checkhooknotempty{post}{#1}\PopPostHook
\ifcsdef{eh@post#1}{%
\expandafter\expandafter\expandafter\eh@CheckWhetherNoEh@hookseparator
\expandafter\expandafter\expandafter{\csname eh@post#1\endcsname}{}{%
\expandafter\eh@csxdefunexpanded\expandafter{%
\romannumeral0%
\expandafter\expandafter\expandafter\eh@PopPostHookLoop
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\expandafter}%
\expandafter\expandafter\expandafter{\csname eh@post#1\endcsname}%
}{eh@post#1}%
}%
}{}%
}%
%%======================================================================
% Helper-macros for \PopPostHook:
%%======================================================================
%% Extract first item from list of arguments separated by \eh@hookseparator
%%
%% \romannumeral0%
%% \eh@ExtractFirstEh@hookseparatorArgLoop
%% {.<list of arguments separated by \eh@hookseparator>\eh@hookseparator\eh@SelDOm}%
%%
%% yields:
%%
%% <first item of list of arguments separated by \eh@hookseparatorArg>
%%..............................................................................
\@ifdefinable\eh@GobbleDot{\def\eh@GobbleDot.{}}%
\@ifdefinable\eh@RemoveEh@hookseparator{\long\def\eh@RemoveEh@hookseparator#1\eh@hookseparator{#1}}%
\@ifdefinable\eh@RemoveFromEh@hookseparatorTillEh@SelDOm{%
\long\def\eh@RemoveFromEh@hookseparatorTillEh@SelDOm#1\eh@hookseparator#2\eh@SelDOm{#1\eh@hookseparator}%
}%
\newcommand\eh@ExtractFirstEh@hookseparatorArgLoop[1]{%
\expandafter\eh@CheckWhetherNull\expandafter{\eh@GobbleToEh@hookseparator#1}%
{%
\eh@exchange{ }{\expandafter\expandafter\expandafter}%
\expandafter\eh@GobbleDot\eh@RemoveEh@hookseparator#1%
}%
{%
\expandafter\eh@ExtractFirstEh@hookseparatorArgLoop
\expandafter{\eh@RemoveFromEh@hookseparatorTillEh@SelDOm#1}%
}%
}%
%%------------------------------------------------------------------------------
%% Extract all items but the last item from list of arguments separated by
%% \eh@hookseparator
%%
%% \romannumeral0%
%% \eh@PopPostHookLoop{}%
%% {<list of arguments separated by \eh@hookseparator>}%
%%
%% yields:
%%
%% <list of arguments separated by \eh@hookseparatorArg with last element removed>.
%%
%% The list must have at least one element. This must be checked by the macro
%% which calls the loop.
%%..............................................................................
\newcommand\eh@PopPostHookLoop[2]{%
%#1 = <collected list items>
%#2 = <remaining list items>
\expandafter\eh@CheckWhetherNoEh@hookseparator\expandafter{\eh@GobbleToEh@hookseparator#2}{%
\expandafter\eh@exchange
\expandafter{%
\romannumeral0\eh@ExtractFirstEh@hookseparatorArgLoop{.#2\eh@hookseparator\eh@SelDOm}%
}{ #1}%
}{%
\expandafter\eh@exchange\expandafter{\expandafter{\eh@GobbleToEh@hookseparator#2}}{%
\expandafter\expandafter\expandafter\eh@PopPostHookLoop
\expandafter\expandafter\expandafter{%
\expandafter\eh@exchange
\expandafter{%
\romannumeral0\eh@ExtractFirstEh@hookseparatorArgLoop{.#2\eh@hookseparator\eh@SelDOm}%
}{#1}\eh@hookseparator
}%
}%
}%
}%
%%------------------------------------------------------------------------------
With the package everyhook you are urged to run things under ε-TeX.
In section 5.1 "Mode-Independent Commands" of the ε-TeX manual, Version 2, February 1998 by The NTS Team — Peter Breitenlohner, Max-Planck-Institut füur Physik, München, on page 17 you find a paragraph about the additional possibilities for ⟨token parameter⟩
.
This paragraph mentions another token-parameter \everyeof
:
The additional possibilities for
⟨token parameter⟩
are:
\everyeof
(tokens to insert when an\input
file ends)
\everyeof
is executed at the end of every \input
file.
\everyeof
is also executed at the end of every pseudo-file generated and input by \scantokens
.
\everyeof
is not executed at the end of pseudo-files generated and input by \detokenize
.
You can nicely use \everyeof
, e.g., for passing \noexpand
to the end of a (pseudo) file for neutralizing within \edef
/\xdef
-contexts the end-of-file-pseudo-token which usually gets attached by (La)TeX and which, if not neutralized, triggers an error-message in case it is encountered while scanning/gathering the text of a ⟨definition⟩
:
\long\def\exchange#1#2{#2#1}%
\long\def\definetest#1#2{%
\expandafter\exchange\expandafter{%
\expandafter\everyeof\expandafter{\the\everyeof}%
}{%
#2%
\everyeof{\noexpand}%
\edef\test{\scantokens{#1}}%
}%
}%
\begingroup
\catcode`\%=12\relax
A\definetest{text text%}{\endgroup}%B
C
\show\test
\csname stop\endcsname
\bye
Perhaps everyhook's facilities can be made available for the \everyeof
-token-parameter as well.
I've allowed myself to create a file UDInterimEveryhook.sty based on your everyhook package where all the changes I've suggested are included:
%% This is file `UDInterimEveryhook.sty'.
%%
%% This file is derived from Stephen Checkoway's file everyhook.sty
%% which forms the LaTeX 2e-package
%% everyhook 2014/11/26 v1.2 (SVN Rev: 12)\ Hooks for low level TeX every X primitives.
%% (<https://ctan.org/pkg/everyhook>)
%%
%% Author of this file: Ulrich Diez.
%% Copyright holder of this file: Ulrich Diez.
%% Copyright (C) 2019 Ulrich Diez.
%%
%% This file is neither for distribution nor for publishing.
%% This file is written by Ulrich Diez for Stephen Checkoway, the
%% author of everyhook.dtx.
%%
%% In order to solve some problems with Stephen Checkoway's
%% LaTeX 2e-package everyhook Ulrich Diez suggests some changes
%% to that package.
%%
%% This file is derived from Stephen Checkoway's package everyhook.
%% This file contains the suggested changes.
%%
%% The only purpose of this file is making it more easy for
%% Stephen Checkoway to test the changes suggested by Ulrich Diez.
%%
%% Permission is granted by Ulrich Diez to Stephen Checkoway
%% to use in the context of creating future releases of the
%% everyhook package those portions of code in this file that are
%% written by Ulrich Diez in whatever ways Stephen Checkoway likes to.
%%
%% Although everyhook 2014/11/26 v1.2 (SVN Rev: 12) was published
%% under the LPPL license, this permission is independent from
%% the licensing-models under which Stephen Checkoway intends to
%% publish future releases of the everyhook package.
%%
%% !!!! Usage/handling of this file and usage/handling of code
%% !!!! exhibited in this file is _not_ at the risk of Ulrich Diez.
%% !!!! Usage/handling of this file and usage/handling of code
%% !!!! exhibited in this file is at the risk of those who use/
%% !!!! handle these things and/or is at the risk of those on
%% !!!! whose behalf usage/handling takes place.
%% !!!!
%% !!!! Ulrich Diez does neither give whatsoever warranties nor
%% !!!! give whatsoever quarantees nor take on whatsoever
%% !!!! liabilites for correctness, completeness, relevance,
%% !!!! accuracy, functuality, quality, anything else
%% !!!! in connection with whatever use or handling of this file
%% !!!! and in connection with whatever use or handling of the
%% !!!! code exhibited in this file. If something breaks, the
%% !!!! user/s usually may herself/himself/themselves cope with
%% !!!! the pieces.
%%
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%////////////////////////////////////////////////////////////////////////////////
% The interim-thingie for testing has another name:
%////////////////////////////////////////////////////////////////////////////////
%% Requires eTeX extensions.
\ProvidesPackage{UDInterimEveryhook}%
[2019/09/07 v0.01beta Hooks for low level
TeX everyX primitives. Interim-work.
Not to be published.]
%////////////////////////////////////////////////////////////////////////////////
\DeclareOption{excludeor}{%
\AtBeginDocument{%
\output\expandafter{%
\expandafter\eh@saveclearallhooks
\the\output
\eh@restoreallhooks
}%
}%
}
\ProcessOptions\relax
\RequirePackage{etoolbox}
\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}{}%
%////////////////////////////////////////////////////////////////////////////////
% Two additional \exandafter added in the line below (-> Problem 1):
%////////////////////////////////////////////////////////////////////////////////
\csuse{eh@every#1}\expandafter{\expandafter\expandafter\csname eh@pre#1\expandafter\endcsname
%////////////////////////////////////////////////////////////////////////////////
% Two previously missing \exandafter added in the line below (-> Problem 1):
%////////////////////////////////////////////////////////////////////////////////
\expandafter\the\expandafter\expandafter\csname eh@private#1\expandafter\endcsname
\csname eh@post#1\endcsname}%
}
\eh@definehook{par}\everypar
\eh@definehook{math}\frozen@everymath
\eh@definehook{display}\frozen@everydisplay
\eh@definehook{hbox}\everyhbox
\eh@definehook{vbox}\everyvbox
\eh@definehook{cr}\everycr
%//////////// Take into consideration the token-parameter \everyeof (<-Problem 4):
\eh@definehook{eof}\everyeof
\undef\eh@definehook
\def\eh@hookseparator{}
\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.}}%
}
%////////////////////////////////////////////////////////////////////////////////
%////////////////////////////////////////////////////////////////////////////////
%////////////////////////////////////////////////////////////////////////////////
\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.}}{}%<-////////// braces moved (-> Problem 2)
}%
%================================================================================
% -> Problem 3
% \PushPreHook, \PopPreHook, \PushPostHook and \PopPostHook:
%================================================================================
% Helper-macros for \PushPreHook, \PopPreHook, \PushPostHook and \PopPostHook:
%--------------------------------------------------------------------------------
% Define a macro from an undelimited macro argument in a way where hashes (#)
% get doubled inside the macro-definition for compensating the circumstance
% that hashes inside the <balanced text> of macro definitions get halved during
% macro expansion
% -- \eh@csxdefunexpanded is called by:\ PushPreHook, \PopPreHook, \PushPostHook
% and \PopPostHook:
%
% \eh@csxdefunexpanded{<argument>}{<csname>}
% -> defines globally a macro whose name is <csname> to expand to the tokens
% that form <argument>.
%
% Syntax with <argument> before <csname> makes applying expansion-and
% token-exchanging trickery with <argument> for first obtaining the <argument>
% more easy.
%
\newcommand\eh@csxdefunexpanded[2]{\csxdef{#2}{\unexpanded{#1}}}%
%................................................................................
% Exchange two undelimited macro arguments and with each of these arguments
% remove the outermost pair of matching surrounding curly braces if present
% -- \eh@exchange is called by: \PushPreHook and \PopPostHook:
%
\newcommand\eh@exchange[2]{#2#1}%
%................................................................................
% Check whether undelimited macro argument contains the token \eh@hookseparator
% -- \eh@CheckWhetherNoEh@hookseparator is called by: \PopPreHook and \PopPostHook:
%
% \eh@CheckWhetherNoEh@hookseparator{<argument>}%
% {<tokens to be delivered in case <argument>
% does not contain a token \eh@hookseparator
% which is not nested in braces.>}%
% {<tokens to be delivered in case <argument>
% does contain a token \eh@hookseparator
% which is not nested in braces.>}%
%
\newcommand\eh@CheckWhetherNoEh@hookseparator[1]{%
\expandafter\eh@CheckWhetherNull
\expandafter{\eh@GobbleToEh@hookseparator#1\eh@hookseparator}%
}%
\@ifdefinable\eh@GobbleToEh@hookseparator{%
\long\def\eh@GobbleToEh@hookseparator#1\eh@hookseparator{}%
}%
% Check whether <argument> is empty:
% \eh@CheckWhetherNull{<argument>}%
% {<tokens to be delivered in case "emptiness"
% was gathered as <argument>}%
% {<tokens to be delivered in case at least
% one token was gathered as <argument>}%
\newcommand\eh@CheckWhetherNull[1]{%
\romannumeral0\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\@firstoftwo{\expandafter}{} \@firstoftwo}%
{\@firstoftwo{\expandafter}{} \@secondoftwo}%
}%
%--------------------------------------------------------------------------------
% \PushPreHook:
%--------------------------------------------------------------------------------
\newrobustcmd\PushPreHook[2]{%
\eh@checkhook{#1}\PushPreHook
\expandafter\eh@csxdefunexpanded\expandafter{%
\romannumeral0%
\expandafter\expandafter
\expandafter \eh@exchange
\expandafter\expandafter
\expandafter {%
\csname eh@pre#1\endcsname}{ #2\eh@hookseparator}%
}{eh@pre#1}%
}%
%--------------------------------------------------------------------------------
% \PushPostHook:
%--------------------------------------------------------------------------------
\newrobustcmd\PushPostHook[2]{%
\eh@checkhook{#1}\PushPostHook
\expandafter\expandafter\expandafter\eh@csxdefunexpanded
\expandafter\expandafter\expandafter{%
\csname eh@post#1\endcsname\eh@hookseparator#2%
}{eh@post#1}%
}%
%--------------------------------------------------------------------------------
%% \PopPreHook
%--------------------------------------------------------------------------------
\newrobustcmd\PopPreHook[1]{%
\eh@checkhooknotempty{pre}{#1}\PopPreHook
\ifcsdef{eh@pre#1}{%
\expandafter\expandafter\expandafter\eh@CheckWhetherNoEh@hookseparator
\expandafter\expandafter\expandafter{\csname eh@pre#1\endcsname}{}{%
\expandafter\eh@csxdefunexpanded
\expandafter{%
\romannumeral0%
\expandafter\expandafter\expandafter\eh@popprehook
\csname eh@pre#1\endcsname
}{eh@pre#1}%
}%
}{}%
}%
%................................................................................
% Helper-macros only for \PopPreHook:
%................................................................................
% \eh@popprehook<\eh@hookseparator-separated list>
% removes the the first \eh@hookseparator-separated item and the first
% \eh@hookseparator behind that item from the
% <\eh@hookseparato-separated list> and delivers a space-token for
% terminating \romannumeral0-expansion; <\eh@hookseparator-separated list>
% must contain a token \eh@hookseparator:
%
\@ifdefinable\eh@popprehook{\long\def\eh@popprehook#1\eh@hookseparator{ }}%
%--------------------------------------------------------------------------------
% \PopPostHook
%--------------------------------------------------------------------------------
\newrobustcmd\PopPostHook[1]{%
\eh@checkhooknotempty{post}{#1}\PopPostHook
\ifcsdef{eh@post#1}{%
\expandafter\expandafter\expandafter\eh@CheckWhetherNoEh@hookseparator
\expandafter\expandafter\expandafter{\csname eh@post#1\endcsname}{}{%
\expandafter\eh@csxdefunexpanded\expandafter{%
\romannumeral0%
\expandafter\expandafter\expandafter\eh@PopPostHookLoop
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\expandafter}%
\expandafter\expandafter\expandafter{\csname eh@post#1\endcsname}%
}{eh@post#1}%
}%
}{}%
}%
%................................................................................
% Helper-macros only for \PopPostHook:
%................................................................................
% Extract first item from list of arguments separated by \eh@hookseparator:
%
% \romannumeral0%
% \eh@ExtractFirstEh@hookseparatorArgLoop%
% {.<list of arguments separated by \eh@hookseparator>\eh@hookseparator\eh@SelDOm}%
%
% yields:
%
% <first item of list of arguments separated by \eh@hookseparatorArg>
%................................................................................
\@ifdefinable\eh@GobbleDot{\def\eh@GobbleDot.{}}%
\@ifdefinable\eh@RemoveEh@hookseparator{%
\long\def\eh@RemoveEh@hookseparator#1\eh@hookseparator{#1}%
}%
\@ifdefinable\eh@RemoveFromEh@hookseparatorTillEh@SelDOm{%
\long\def\eh@RemoveFromEh@hookseparatorTillEh@SelDOm%
#1\eh@hookseparator#2\eh@SelDOm{#1\eh@hookseparator}%
}%
\newcommand\eh@ExtractFirstEh@hookseparatorArgLoop[1]{%
\expandafter\eh@CheckWhetherNull\expandafter{\eh@GobbleToEh@hookseparator#1}{%
\eh@exchange{ }{\expandafter\expandafter\expandafter}%
\expandafter\eh@GobbleDot\eh@RemoveEh@hookseparator#1%
}{%
\expandafter\eh@ExtractFirstEh@hookseparatorArgLoop
\expandafter{\eh@RemoveFromEh@hookseparatorTillEh@SelDOm#1}%
}%
}%
%................................................................................
% Extract all items but the last item from list of arguments separated by
% \eh@hookseparator:
%
% \romannumeral0%
% \eh@PopPostHookLoop{}%
% {<list of arguments separated by \eh@hookseparator>}%
%
% yields:
%
% <list of arguments separated by \eh@hookseparatorArg with last element removed>.
%
% The list must have at least one element. This must be checked by the macro
% which calls the loop.
%................................................................................
\newcommand\eh@PopPostHookLoop[2]{%
%#1 = <collected list items>
%#2 = <remaining list items>
\expandafter\eh@CheckWhetherNoEh@hookseparator
\expandafter{%
\eh@GobbleToEh@hookseparator#2}{%
\expandafter\eh@exchange
\expandafter{%
\romannumeral0%
\eh@ExtractFirstEh@hookseparatorArgLoop{.#2\eh@hookseparator\eh@SelDOm}%
}{ #1}%
}{%
\expandafter\eh@exchange
\expandafter{%
\expandafter{%
\eh@GobbleToEh@hookseparator#2}}{%
\expandafter\expandafter\expandafter\eh@PopPostHookLoop
\expandafter\expandafter\expandafter{%
\expandafter\eh@exchange
\expandafter{%
\romannumeral0%
\eh@ExtractFirstEh@hookseparatorArgLoop{.#2\eh@hookseparator\eh@SelDOm}%
}{#1}\eh@hookseparator
}%
}%
}%
}%
%--------------------------------------------------------------------------------
% Remarks:
%
% \PushPreHook, \PopPreHook, \PushPostHook and \PopPostHook and the underlying
% macro mechanisms work without defining temporary macros.
%
% The only token not allowed in the second arguent of \PushPreHook, \PopPreHook,
% \PushPostHook and \PopPostHook is the token \eh@hookseparator.
%
% The internal tail recursive loop \eh@ExtractFirstEh@hookseparatorArgLoop
% makes use of the token \eh@SelDOm in order to reduce the amount of
% iterations needed for extracting the first item that is delimited by
% \eh@hookseparator. Nonetheless you may use the token \eh@SelDOm.
% If you do so the only effect will be: In case such an \eh@SelDOm is not in the very
% first item of the \eh@hookseparator-list, the loop will need more iterations.
%
%////////////////////////////////////////////////////////////////////////////////
%////////////////////////////////////////////////////////////////////////////////
%////////////////////////////////////////////////////////////////////////////////
\def\eh@clearhook#1{%
\global\csdef{eh@#1}{}%
}
\newrobustcmd\ClearPreHook[1]{%
\eh@checkhook{#1}\ClearPreHook
\eh@clearhook{pre#1}%
}
\newrobustcmd\ClearPostHook[1]{%
\eh@checkhook{#1}\ClearPostHook
\eh@clearhook{post#1}%
}
\def\eh@savehook#1#2{%
\letcs#2{eh@#1}%
}
\def\eh@restorehook#1#2{%
\global\cslet{eh@#1}#2%
}
\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%
}
\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
%//////////// Take into consideration the token-parameter \everyeof (<-Problem 4):
\global\eh@savehook{preeof}\eh@or@preeof
\global\eh@savehook{posteof}\eh@or@posteof
%///////////////
\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}%
%//////////// Take into consideration the token-parameter \everyeof (<-Problem 4):
\eh@clearhook{preeof}%
\eh@clearhook{posteof}%
%///////////////
}
\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
%//////////// Take into consideration the token-parameter \everyeof (<-Problem 4):
\eh@restorehook{preeof}\eh@or@preeof
\eh@restorehook{posteof}\eh@or@posteof
%///////////////
}
\endinput
%%
%% End of file `UDInterimEveryhook.sty'.
This way you can easily test by "commenting out" \usepackage...
-statements for alternately loading either everyhook.sty or UDInterimEveryhook.sty in order to see the difference in behavior between the two package variants.
I also have made a small test file:
%% Author of this file: Ulrich Diez.
%% Copyright holder of this file: Ulrich Diez.
%% Copyright (C) 2019 Ulrich Diez.
%%
%% This file is written by Ulrich Diez for Stephen Checkoway, the
%% author of everyhook.dtx.
%%
%% In order to solve some problems with Stephen Checkoway's
%% LaTeX 2e-package everyhook Ulrich Diez suggests some changes
%% to that package.
%%
%% The only purpose of this file is making it more easy for
%% Stephen Checkoway to test the changes suggested by Ulrich Diez.
%%
%% Permission is granted by Ulrich Diez to Stephen Checkoway
%% to use in the context of creating future releases of the
%% everyhook package those portions of code in this file that are
%% written by Ulrich Diez in whatever ways Stephen Checkoway likes to.
%%
%% Although everyhook 2014/11/26 v1.2 (SVN Rev: 12) was published
%% under the LPPL license, this permission is independent from
%% the licensing-models under which Stephen Checkoway intends to
%% publish future releases of the everyhook package.
%%
%% !!!! Usage/handling of this file and usage/handling of code
%% !!!! exhibited in this file is _not_ at the risk of Ulrich Diez.
%% !!!! Usage/handling of this file and usage/handling of code
%% !!!! exhibited in this file is at the risk of those who use/
%% !!!! handle these things and/or is at the risk of those on
%% !!!! whose behalf usage/handling takes place.
%% !!!!
%% !!!! Ulrich Diez does neither give whatsoever warranties nor
%% !!!! give whatsoever quarantees nor take on whatsoever
%% !!!! liabilites for correctness, completeness, relevance,
%% !!!! accuracy, functuality, quality, anything else
%% !!!! in connection with whatever use or handling of this file
%% !!!! and in connection with whatever use or handling of the
%% !!!! code exhibited in this file. If something breaks, the
%% !!!! user/s usually may herself/himself/themselves cope with
%% !!!! the pieces.
%%
\documentclass{article}
\usepackage{UDInterimEveryhook}[2019/09/07]
%\usepackage{everyhook}
\newcommand\ThisShallNotBeExpanded{Oh no!}%
\makeatletter
\message{^^JShowing \string\eh@everypar^^J====================^^J}
\showthe\eh@everypar
\message{^^JDoing Pre-Hook-Things^^J=====================^^J%
^^JPushing Pre-Hook^^J----------------^^J^^J}
\PushPreHook{par}{D\ThisShallNotBeExpanded\def\dummy################1{This is the argument ################1}}
\show\eh@prepar
\PushPreHook{par}{C\ThisShallNotBeExpanded}
\show\eh@prepar
\PushPreHook{par}{B\ThisShallNotBeExpanded}
\show\eh@prepar
\PushPreHook{par}{A\ThisShallNotBeExpanded}
\show\eh@prepar
\message{^^JPoping Pre-Hook^^J----------------^^J^^J}
\PopPreHook{par}
\show\eh@prepar
\PopPreHook{par}
\show\eh@prepar
\PopPreHook{par}
\show\eh@prepar
\PopPreHook{par}
\show\eh@prepar
\message{The next pop is expected to yield an error-message:^^J(Press return to proceed.)}%
\immediate\read-1to\scratchy
\PopPreHook{par}
\show\eh@prepar
\message{^^JDoing Post-Hook-Things^^J======================^^J%
^^JPushing Post-Hook^^J-----------------^^J^^J}
\PushPostHook{par}{A\ThisShallNotBeExpanded\def\dummy################1{This is the argument ################1}}
\show\eh@postpar
\PushPostHook{par}{B\ThisShallNotBeExpanded}
\show\eh@postpar
\PushPostHook{par}{C\ThisShallNotBeExpanded}
\show\eh@postpar
\PushPostHook{par}{D\ThisShallNotBeExpanded}
\show\eh@postpar
\message{^^JPoping Post-Hook^^J-----------------^^J^^J}
\PopPostHook{par}
\show\eh@postpar
\PopPostHook{par}
\show\eh@postpar
\PopPostHook{par}
\show\eh@postpar
\PopPostHook{par}
\show\eh@postpar
\message{The next pop is expected to yield an error-message:^^J(Press return to proceed.)}%
\immediate\read-1to\scratchy
\PopPostHook{par}
\show\eh@postpar
\stop
Sincerely
Ulrich Diez
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.