There is no \tl
. I think you might be getting a bit confused because you're seeing expl3 syntax (thus the \ExplSyntaxOn
…\ExplSyntaxOff
surrounding the code. The key documentation for this can be found by typing texdoc expl3
for a short overview and texdoc interface3
for a long detailed but not necessarily easy to follow account. Alan Xiang's LaTeX3 tutorial is a more gentle introduction and a good starting point.
But let's go through your code a bit at a time to try to understand it:
\ExplSyntaxOn
This is the signal that we're in expl3 mode. In this mode, command names can contain _
and :
so what you thought was \tl
, was actually a number of different command names that began with \tl
but had more to them than that. Also, all spaces in this mode are ignored (if you need a literal space, ~
will give that, while \nobreakspace
can be used if you need a non-breaking space.
\int_new:N \crossref_int
\int_new:N \vs_int
\tl_new:N \crossref_tl
Here we're declaring a few new variables¹. The standard naming for commands is to use \
⟨scope⟩_
⟨module⟩_
⟨description⟩_
⟨type⟩ to name these. Alas, this code doesn't follow that convention except for putting the type at the end. We also see some commands. The expl 3 convention for commands is \
⟨module⟩_
⟨description⟩:
⟨arg-spec⟩ which is followed internally at least. That :
is helpful for noticing when something is to be a command vs a variable which can help with at least one aspect of TeX programming’s inscrutability. All expl3 commands will have :
, even if they don’t take arguments. Here we see an arg-spec of N
which refers to a single token which here is a LaTeX control sequence name. So what we've done here is to define two new integer variables and one token list (that's the \tl
you're seeing all over the place).
% insert a cross reference
\NewDocumentCommand {\crossref} {m}
Here we define a new document command, \crossref
with a single mandatory argument. This is roughly equivalent to \newcommand*{\crossref}[1]{...}
You can get the full story on \NewDocumentCommand
by typing texdoc xparse
at a command line.
{
\int_compare:nNnT { \crossref_int } > { 25 }
{
\int_set:Nn \crossref_int { 0 }
}
Now we've actually begun the command definition. We're doing an integer comparison. The arg spec here is nNnT
. The n
s refer to arguments which are delimited with braces. The N
is a single token again, although this time its the >
and the T
is a special case of n
which refers to a block of code to be executed if the comparison is true (there's also F
and both could be used in a comparison, so, e.g., \int_compare:nNnTF
which take two blocks of code after the comparison code to execute the true and false branches.
So in this case, if \crossref_int
is greater than 25, we reset it to 0. Since, as we'll see later, we're using it to generate alphabetic indices, this makes perfect sense.
\int_incr:N \crossref_int
And here, we increment the value of \crossref_int
.
% NOT PRESENTLY REQUIRING LETTERED SUPERSCRIPTS
% \textsuperscript{ \emph { \int_to_alph:n { \crossref_int } } }
\tl_if_empty:NF \crossref_tl
{
\tl_gput_right:Nn \crossref_tl { ~ }
}
Now here's where the token lists come into play. Token lists are, as there name indicates, lists of tokens. In this case, we look at the value of \crossref_tl
and see if its empty. If it's not (note the F
arg-spec on \tl_if_empty
), then we call \tl_gput_right:
to add a space to the right. The g
in gput
means global and this is one of the places where following the conventions of expl3 would be useful. One of the limitations of TeX is that if you do both global and local manipulations on its register variables, you can end up with a memory leak. Knuth's recommendation for this was to adopt a convention of, e.g., only doing global operations on even-numbered registers and local on odd.²
\tl_gput_right:Nx \crossref_tl
{
% NOT PRESENTLY REQUIRING LETTERED SUPERSCRIPTS
% \exp_not:N \textsuperscript
% {
% \exp_not:N \emph { \int_to_alph:n { \crossref_int } }
% }
\, #1
}
}
And then there's the main work of this command. Putting a new token list into the right side of the \crossref_tl
token list. Note that are arg list here is Nx
the x
is saying that we want to expand the contents of the list before appending it. This would allow the commented code to be executed before its added to the token list which is what we would want since we care about the value of \crossref_int
at the time the command is executed. If we had not done that then we would end up with a token list of, e.g.,
d note 1 d note 2 d note 3 d note 4
instead of the desired
a note 1 b note 2 c note 3 d note 4
%Sample output
% insert chapter marker
\NewDocumentCommand {\ch} {m}
{
\int_gset:Nn \vs_int {1}
\lettrine [findent=0.5em,nindent=0em] { #1 } {}
}
This one is pretty straightforward. We define \ch
to take a single mandatory argument and we use the lettrine
class³ to set the chapter number in drop cap style. We also (globally) set our counter \vs_int
to 1.
% output cross references from previous verse and insert verse marker
\NewDocumentCommand {\vs} {m}
{
\tl_if_empty:NF \crossref_tl
{
\sidebar
{
\textbf { \int_use:N \vs_int } \, \tl_use:N \crossref_tl % ❶
}
}
\int_gset:Nn \vs_int { #1 } % ❷
\tl_gclear:N \crossref_tl % ❸
\textsuperscript { #1 \, } % ❹
}
So here, we define \vs
also with a single mandatory argument, the verse number, which is set as a superscript before the text of the verse ❹. But before that, we will output the cross-references, if any. We look in \crossref_tl
to see if its empty (\tl_if_empty
) and if it's not (thus the F
in the arg spec), we use \sidebar
to set the value of \vs_int
in boldface (we have to use \int_use:N
to get the value for this purpose) and then the contents of the \crossref_tl
token list (again, \tl_use:N
is necessary to get that value ❶). Then we set the value of \vs_int
to the number passed in the argument to \vs
❷ and clear the \crossref_tl
token list ❸.
% output any remaining cross references
\AtEndDocument
{
\tl_if_empty:NF \crossref_tl
{
\sidebar
{
\textbf { \int_use:N \vs_int } \, \tl_use:N \crossref_tl
}
}
}
The final bit of code is to make sure that the cross references that remain are output at the end of the document. This is done using the \AtEndDocument
hook (although the newer style would be to instead write \AddToHook{enddocument}
(LaTeX has added extensive “hook” mechanisms for class and package writers. See texdoc source2e
for the gory details). The code for setting this is essentially identical to the code that was used in defining \vs
so I'll not say anything more about that.
\ExplSyntaxOff
And then we turn off the expl syntax so that the rest of our document will be fine.
As for your original question, I'm guessing the problem that you're trying to resolve lies in the definition of \sidebar
, wherever that comes from.
TeX does not exactly have variables. There are 256 registers of various types (counters–\count
s in plain TeX-speak which hold integers, lengths (plain TeX calls these \dimen
s, glues (plain TeX calls these \skip
s and they're essentially lengths which can stretch or shrink), token lists, boxes, muskips, inserts, read and write streams and math font families. Most of these are limited to 256 registers with some registers reserved (e.g., \count0
is the page number). Most “variables” in TeX are simply macros, which makes life a bit difficult and expl3 attempts to impose some order on things although there is no enforcement of this order as we'll see).
Or maybe it's the other way around. I'm going on memories from 1986 here.
This is a good example of the correct use of lettrine
. Since a drop cap doesn't have any semantic value it really shouldn't be set directly in the text but should be part of other code. It's possible to, without too much effort, use lettrine
’s capabilities to automatically set the first letter of the first paragraph after \chapter
without any additional markup.