[Tex/LaTex] What do \setunit and \newunit do

biblatexmacros

I'm learning how to customize BibLaTeX styles at the moment. When digging through the *.bbx files I often encounter the commands \setunit{...} and \newunit. The most common use of \setunit{...}seems to be \setunit{\addspace}, but there are many other applications as well. Sometimes also the starred version \setunit*{...} is used. \newunit seemingly takes no arguments and has no starred version.

Many bibliography macros I'm modyfing use these commands so I'd really like to understand what their effect is. I wasn't able to find any information about them (neither on this site nor in the BibLaTeX documentation nor via web search). As they always appear together and also because of the similar names I'm guessing there is some connection between the two, so I'm asking both in one question.

Best Answer

The relevant sections of the biblatex documentation are §4.7 Punctuation and Spacing and §4.11.7 Using the Punctuation Tracker.

Thanks to the punctuation tracker you do not have to worry about double punctuation, spurious spaces or missing fields.

To use the punctuation tracker you have to use \setunit. Instead of writing the punctuation command directly as in

\printfield{title}%
\addcomma\space
\printfield{edition}%
\addcomma\space
\printfield{note}%

we write

\printfield{title}%
\setunit{\addcomma\space}%
\printfield{edition}%
\setunit{\addcomma\space}%
\printfield{note}%

In the first case biblatex would immediately print a comma and space after the title and the edition. But if no edition is present we would be left with

Title, , note

Using \setunit and the punctuation tracker, however, we get

Title, note

That is because \setunit does not actually print its argument. Instead it places its argument in a buffer. The buffer is printed as soon as a \printtext, \printfield, \print... command following it prints something. In the example above the first \setunit sends its argument off to the buffer, \printfield{edition} does nothing, the second \setunit sends its argument off replacing the earlier value. Then \prinfield{note} prints something and biblatex inserts the punctuation buffer right before it prints the contents of the note field. This is what the biblatex documentation refers to as asynchronous treatment of text/\print... (which is written immediately) and punctuation (which is only printed when necessary).

Because the buffer is overwritten by subsequent \setunits, both

\printfield{title}%
\setunit{\addperiod\space}%
\printfield{edition}%
\setunit{\addperiod\space}%
\printfield{note}%

and

\printfield{title}%
\setunit{\addcomma\space}%
\printfield{edition}%
\setunit{\addperiod\space}%
\printfield{note}%

give

Title. Note

if the edition field is empty.

There is also \setunit* that only inserts its argument into the buffer if the last \print... command before it printed something. So

\printfield{title}%
\setunit{\addperiod\space}%
\printfield{edition}%
\setunit*{\addcomma\space}%
\printfield{note}%

gives

Title. Note

if the edition is missing and

Title. Edition, note

if that is not the case.

Since the punctuation tracker only 'sees' text printed via \print... commands. You should not write hard-coded text directly into a bibmacro, it should always go into a \printtext. This is different for \DeclareFieldFormat, hard coded text is OK there, \printtext within \DeclareFieldFormat could even confuse the tracker.

\newunit is for all intents and purposes the same as \setunit{\newunitpunct}. In fact I was surprised that internally it is not defined like that; the actual definition is on a much lower level. So \newunit does not need an argument. \newunit is used as the 'standard' way to separate \print... commands, \setunit is only used for occasions where \newunitpunct does not apply (of which there are many).

\newblock is similar to \newunit, but it has no equivalent to \setunit, i.e. no \setblock or similar. It marks the start of a new block. Blocks are larger than the units marked by \newunit. A start of a new block inserts \newblockpunct after the punctuation mark inserted by the punctuation buffer.

Related Question