These are LaTeX kernel macros that are associated with environments. In simple terms anything that is enclosed with a \begin{foo}...\end{foo}
is an environment. For example a figure or a table.
Every time you insert a table a counter is incremented. This counter let us call it foo
has an associated macro named \p@foo
. This macro expands to a printed `reference prefix' of counter
foo.
Any \ref
to a value created by counter foo
will produce the expansion of \p@foo\thefoo
when the \label
command is executed. \thefoo
justs prints the value of counter `foo'.
Change foo
to figure
or table
and it will make more sense.
The \def
part defines the macro. You can for example say \def\milan{Milan Ramaiyan}
and every time you type \milan
it will expand too .. Milan Ramaiyan. The @
symbol is just a special symbol used by TeX and LaTeX to avoid overriding commands accidentally. It needs special treatment and that is why the makeatletter
and makeatother
are required.
It's one of the uncountable ways to check whether an argument is empty. Almost all of them suffer of some drawback: in the case at hand, the argument mustn't be \\
.
What does \ifx
do? It compares the two tokens following it, without expanding them. The test return success if both tokens are equal in the sense of \meaning
or \show
:
if they are characters (or control sequences \let
to a character), they must represent the same (character code, category code) pair
if they are control sequences (but not \let
to a character), they must have the same meaning; the cases are too many to list them all.
Before analyzing the macro, we should know something about TeX conditional: the abstract form is
\ifZ<test><true text>\else<false text>\fi
where \ifZ
denotes one of the primitive conditionals. The <test>
can take many forms, depending on \ifZ
(it's empty, in some cases); what is important is that the <true text>
is everything that goes from the end of <test>
to \else
(or \fi
if \else
is missing).
So let's see what happens when we call \mycommand{abc}
, that is, the default argument, which is empty, is substituted to #1
: the tokens that TeX sees are
\ifx\\\\<true>\else<false>\fi
Of course the test is true, because the tokens that follow \ifx
are both \\
.
When we call \mycommand[xyz]{abc}
, instead, TeX sees
\ifx\\xyz\\<true>\else<false>\fi
and TeX compares \\
to x
and they are different. But now the <true text>
is
yz\\<true>
(remember: the <true text>
is what goes from the test to the \else
) and it will be ignored altogether.
This test is quite safe, because it doesn't do expansion; however it might fail miserably if the user calls \mycommand[\\]{abc}
, so often different delimiter tokens are used, which are supposed not to creep into user's input (for instance \uchyph
or \vfuzz
). Another similar test might be
\if\relax\noexpand#1\relax
with the caveat that \if
does expand what's next until two unexpandable tokens remain. The first token is \relax
, which is unexpandable. The second one will be what becomes of the expansion of \noexpand
, that is, the first token of #1
(if non empty) but made unexpandable; if #1
is empty, then \noexpand
applies to \relax
, resulting again in \relax
because it's unexpandable.
In both cases some token is reserved (\\
in the first case, \relax
in the second one). The safest test is
\if\relax\detokenize{#1}\relax
because the expansion of a non empty #1
can never give a first token equivalent to \relax
: even if #1
is \relax
, \detokenize{\relax}
will give the string \relax
(the first token of which is the character \
).
Again, if #1
is empty, the test compares \relax
to \relax
; if #1
is not empty, everything will be ignored up to the \else
. Of course it requires that an engine with the e-TeX extensions is run: it won't work with "Knuth TeX".
Best Answer
For our purposes,
\begin{#1}
is roughlyand
\end{#1}
is roughlySince
\expandafter
expands\if@endpe
before the group ends, the value of the switch that is used is the one within the environment. If the\csname #1\endcsname
part of a\begin{#1}
features\@endpetrue
, then\@doendpe
will be expanded. However, it will be expanded outside the environment, where the switch has been returned to its former value.Consider the following document. The environment
parenvA
suppresses the indentation afterwards. In the second case,\@endparenv
is called within two groups, and causes\@doendpe
to be called still within theparenvB
environment. If the definition of\@doendpe
did not have\@endpetrue
, then it would simply define\par
and\everypar
within theparenvB
environment. These definitions would disappear at the end of the group, and the next paragraph would be indented. So instead,\@doendpe
makes sure to carry the truth of the switch with it beyond environment boundaries, until the next\par
or\everypar
.Once this is established, both
\par
and\everypar
must have\@endpefalse
, otherwise the last paragraph in the example above would lose its indentation: indeed, the\@doendpe
triggered just outside theparenvA
environment contains\@endpetrue
, but we don't want the indentation to be suppressed after that\end{parenvB}
, because there has already been a paragraph.Now why do we need to work with both
\everypar
and\par
? Because there are actually two cases. If the user leaves no blank line after\end{parenvA}
, then the first letter, inherently horizontal for TeX, causes\everypar
to be inserted, and to eat the indentation (with\lastbox
). However, if the user leaves a blank line, TeX's eyes replace that by a\par
token, which resets the normal definitions of\par
and\everypar
, and do not eat any indentation (try adding some blank lines in the file above and see what happens).For your bonus question, well, if you remove those lines, the indentation will only be removed if the next
\par
(blank line) or\everypar
(triggered by horizontal material) is within the same group/environment. Not necessarily what you want.