\makeatletter
and \makeatother
are needed in order to allow using command names with @
in them. There is nothing really special about it.
The first idea is to use \NewDocumentCommand{\DTLfetchifnull}{mmmmmmm}
if it is available, otherwise the standard \newcommand{\DTLfetchifnull}[7]
is used (for compatibility with older documents).
With newer releases we essentially get
\NewDocumentCommand\DTLfetchifnull{mmmmmmm}
{%
\begingroup%
\protected@edef\@dtl@dogetrowforvalue{%
\noexpand%
\endgroup
\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
}\@dtl@dogetrowforvalue%
\ifx \dtl@rowidx\dtlnovalue%
\expandafter\@secondoftwo%
\else%
\expandafter\@firstoftwo%
\fi%
{%
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
}{%
#7%
}%
}%
that shows not really good programming style. For instance, there are several useless %
, but they're not harmful, just annoying. Also the first \noexpand
is useless, because `\endgroup is not expandable. I'd write it as
\NewDocumentCommand\DTLfetchifnull{mmmmmmm}
{%
\begingroup
\protected@edef\@dtl@dogetrowforvalue{%
\endgroup
\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
}\@dtl@dogetrowforvalue
\ifx \dtl@rowidx\dtlnovalue
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi
{%
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
}{%
#7%
}%
}
If an older LaTeX release, the first line would be \newcommand{\DTLfetchifnull}[7]
.
The idea is to define \@dtl@dogetrowforvalue
to yield
\endgroup
\dtlgetrowindex{\dtl@rowidx}
{expansion of #1}
{expansion of \dtlcolumnindex{#1}{#2}}
{expansion of #3}
and then the scratch macro \@dtl@dogetrowforvalue
will be executed, which will assign a meaning to \dtl@rowidx
, which can be \dtlnovalue
(depending on the arguments #1
, #2
and #3
. The initial \endgroup
will balance the already digested \begingroup
and the definition of \@dtl@dogetrowforvalue
will be forgotten as soon as \endgroup
is executed (but the expansion of \@dtl@dogetrowforvalue
has already been placed on the input stream, so there is no problem with undefining it).
Next the token is compared with \dtlnovalue
. The construction
\if<something>
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi
{tokens A}
{tokens B}
is very common in LaTeX programming. If the test returns true, tokens B
will be used, otherwise tokens A
.
So, if \dtl@rowidx
turns out to be \dtlnovalue
, the argument #7
will be used. Otherwise it will be some legal row index and
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
will be used. Finding out what this does needs studying the manual of datatool
.
amsmath
allows the end user to insert their own tags for numbered equations and therefore collects the body of math environments before processing them. This allows for proper parsing of the content, possibly delaying the execution of \label
only after the equation
counter has been stepped. It does, however, retain access to the original LaTeX \label
via \ltx@label
, which is appropriate for your use:
\documentclass[fleqn]{article}
\usepackage{amsmath}
\makeatletter
\newcommand{\ltxlabel}{\ltx@label}% User-level access to original LaTeX \label
\makeatother
\begin{document}
\newcounter{mycounter}
\refstepcounter{mycounter}\label{foo}\ref{foo}% 1
\refstepcounter{mycounter}\label{bar}\ref{bar}% 2
\begin{equation} x\refstepcounter{mycounter}\ltxlabel{baz}\ref{baz} \end{equation}
\ref{baz}% 3
\refstepcounter{mycounter}\label{qux}\ref{qux}% 4
\end{document}
\ltxlabel
(or \ltx@label
) will be executed immediately, using whatever counter was previously stepped (via \refstepcounter
) as a label reference. In contrast, \label
will only be used to reference the equation
counter under amsmath
.
Best Answer
Here's a way with
\@ifundefined
and usinglatex.ltx
core features.If the label
KN:#1
is undefined, a reference toFN:#1
is used (or at least tried to do so.Another way would use
\getrefnumber
etc. byrefcount
package.