In the following I will use note
instead of source
(since source
is not known in the default data model it will not be passed on to the .bbl
file - I assume you have a custom .dbx
set up).
Use \setunit{\addspace}
instead of literal space
You only need a \setunit{\addspace}
between the two \print...
commands to get things working
%\RequirePackage{filecontents}
\begin{filecontents}{\jobname.bib}
@image{MyImg,
author = {{Addison-Wesley}},
note = {\cite{Rossing1990}},
}
@image{MyImg2,
author = {{Addison-Wesley}},
note = {\cite[45]{Rossing1990}},
}
@book{Rossing1990,
author = {Thomas D. Rossing},
date = {1990},
}
\end{filecontents}
\documentclass{article}
\usepackage[style=authoryear-comp]{biblatex}
\addbibresource{\jobname.bib}
\DeclareCiteCommand{\mycite}{}{%
\printfield{note}%
\setunit{\addspace}%
\printnames[given-family]{author}%
}{}{}
\begin{document}
This citation includes a semicolon between \verb|\printfield| and \verb|\printnames| (which I am trying to get rid of):\\
\mycite{MyImg}\\
This citation doesn't (which is what I want):\\
\mycite{MyImg2}\\
\end{document}
Why does \setunit
help?
The punctuation tracker
biblatex
has a special approach to punctuation between fields or in general \print...
commands. Punctuation should not be inserted directly, instead it s stored in a buffer and printed out only on demand. This asynchronous approach to punctuation vis-à-vis text makes it easy to avoid unwanted double punctuation.
You can read all about the punctuation tracker in §4.11.7 Using the Punctuation Tracker of the biblatex
manual, the short version is as follows:
Whenever punctuation is desired, that punctuation is not inserted directly, it is wrapped in \setunit
(the often used \newunit
is equivalent to \setunit{\newunitpunct}
with \newunitpunct
defaulting to \addperiod\space
). A typical snippet would be (from volume+number+eid
in standard.bbx
)
\printfield{volume}%
\setunit*{\adddot}%
\printfield{number}%
\setunit{\addcomma\space}%
\printfield{eid}
When \setunit
is encountered (we'll come to the starred version \setunit*
in a second), biblatex
stores its argument in the punctuation buffer, the command itself prints nothing. The punctuation buffer can be overwritten by subsequent \setunit
s and so \setunit{X}\setunit{Y}
leaves only Y
in the buffer. The buffer is printed and emptied at the next \print...
command that actually prints anything.
Suppose that in our example above, the entry has a volume
and an eid
field, but no number
field. When the snippet is processed the volume
will be printed, \setunit*
inserts \adddot
into the punctuation buffer. There is no number
, so \printfield{number}
does nothing. \setunit{\addcomma\space}
sends \addcomma\space
to the buffer and replaces its earlier value \adddot
. Then \printfield{eid}
prints the eid
, but before that the punctuation buffer is printed and emptied. This results in
<volume>
, <eid>
If a number
had been present, we would have ended up with
<volume>
.<number>
, <eid>
The starred version \setunit*
checks if the \print...
command immediately preceding it printed something. If that is the case it behaves like \setunit
, if not it discards it argument and does nothing. So in the example a difference would be visible if there was a number
but no volume
. Suppose that before the snippet above \printtext{Blah}\setunit{\addcomma\space}
had inserted \addcomma\space
into the punctuation buffer. With volume
we would get
Blah, <volume>
.<number>
, <eid>
But if there is no volume and \setunit
were used, the \adddot
would overwrite the \addcomma\space
to give
Blah.<number>
, <eid>
With \setunit*
nothing happens to the punctuation buffer if volume
is missing and so we get
Blah, <number>
, <eid>
because \addcomma\space
remains in the buffer even after \printfield{volume}
that did nothing and \setunit*{\adddot}
.
Punctuation in authoryear-comp
's \cite
The cite macros of authoryear-comp
can be simplified to the following scheme (have a look at \DeclareCiteCommand{\cite}
and \newbibmacro{cite}
in authoryear-comp.cbx
)
Loopcode
<Lots of `\print...` commands>
\setunit{\multicitedelim}
postcode
\iffieldundef{postnote}
{}
{\setunit{\postnotedelim}%
\printfield{postnote}}
The loopcode is executed once for every entry you cite (so \cite{sigfridsson,nussbaum}
would go through the loopcode once for sigfridsson
and then for nussbaum
), the postcode is executed at the end after the loop.
If you \cite
something without a postnote the \cite
command leaves a \multicitedelim
in the punctuation buffer even after it is finished. This is because the last line of the loopcode is \setunit{\multicitedelim}
and the postcode is effectively skipped if postnote
is empty. Normally this is not a problem, since \cite
is usually called in a context where the punctuation tracker does not control its surroundings as well - normally \cite
is not followed by a \print...
command - and so the buffer remains set, but is not printed. The next \cite
(or any high-level biblatex
command for that matter) clears the buffer before it does its work, so there is no harm in leaving the buffer non-empty after you are done. In your application, however, there is a \printfield
after the \cite
and so that \printfield
sees the non-empty punctuation buffer and inserts it before it prints its contents.
If you have a postnote
, then after the loopcode has done its thing and left \multicitedelim
in the punctuation buffer, we enter the loopcode, take the second branch and are met with \setunit{\postnotedelim}
. So \multicitedelim
in the buffer is replaced with \postnotedelim
, then \printfield{postnote}
prints and empties the punctuation buffer and finally prints the postnote
. Note that after this chain of events the punctuation buffer is empty. The \printfield
that comes after the \cite
has no punctuation to insert and simply prints its text.
Note that this situation came about specifically because of the implementation details of authoryear-comp
's citation macros. This would not have happened with authoryear
's citation commands. authoryear
does not end its loopcode with \setunit{\multicitedelim}
, the \multicitedelim
is inserted with the sepcode argument to \DeclareCiteCommand
. This can't be done for authoryear-comp
and so there the (generally) stylistically questionable \setunit{\multictedelim}
at the end of the loopcode had to be used.
Conclusion
Punctuation and spaces should always be handled by the punctuation tracker with \setunit
. Never insert spaces or punctuation directly between \print...
commands.
I should add that if at all possible \cite
should be avoided in .bib
entries and the bibliography. For some applications the related
function might be a better fit, but I assume in other cases a work-around is not readily available and needs some thought.
What you are doing here in effect nests citation commands. Usually biblatex
actively discourages nested citation commands (anyone who has tried \cite[\cite{nussbaum}]{sigfridsson}
knows that), because they could lead to confusion for biblatex
's many tracking features (after \cite[\cite{nussbaum}]{sigfridsson}
what should "ibid." refer to? - and even if we decide that it would be sensible to mean sigfridsson
that would be hard to enforce since nussbaum
is actually processed last and biblatex
's trackers have to be global, so no amount of grouping can help us). This might be less of an issue for this highly specialised citation command that is only used in a controlled environment, but it could definitely lead to confusion and unexpected behaviour in normal cite commands.
biblatex
provides. Do you know them?related
facilities would be sufficient to implement this. Essentially I am (mis)using biblatex as a database for my figures.\newcommand{\mycaption}[3][]{\cite[#1]{#2} #3}
to be then used as\mycaption[45]{Rossing1990}{Addison-Wesley}
?