Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Please consider the following MWE, compiled with lualatex test.tex (+ bibtex test + lualatex test.tex):

\documentclass[twoside,a4paper]{book}

\usepackage{lua-visual-debug}
\usepackage{lipsum}
\usepackage{biblatex}
\addbibresource{biblatex-examples.bib}


% note: here the behavior is the same, 
% regardless if \thefield{title} (expandable)
% or \printfield{title} (non-expandable) is used:
%
\newbibmacro*{myCite}{%
\section*{The title: \thefield{title}} %
}

\DeclareCiteCommand{\myCite}%
{}%
{%
\usebibmacro{myCite}}%
{}%
{}%

\def\tracingboxes{\showboxbreadth = \maxdimen
  \showboxdepth = \maxdimen}%


\begin{document}

\tracingpages=1 % pages
\tracingoutput=1 % boxes
\tracingboxes

\section*{Thesting one}

\lipsum[1]

\cleardoublepage

\myCite{vangennep}

\lipsum[2]

\end{document}

In it, I have a directly called \section* on top of the page - and a \section* on top of the page called via a custom cite command (\myCite, implemented through biblatex package functionality). (Both sections start with "Th", so I have a marker for debugging)

The problem is that the two \section*s do not "align" - that is, do not start at the same vertical position (image produced via
montage -density 150 -bordercolor LimeGreen -border 1 test.pdf[0] test.pdf[2] -geometry +2+2 -tile 2x1 out.png
):

out.png

In other words, the \section* called via \myCite has some extra vertical space on top of page. And since (apparently) one cannot just reset the page vertical space on top (especially not by calling internal “command codes”) - I'd like to know:

  • where does this vertical space come from; and
  • how to eliminate it?

In particular, I'm interested in somehow tracking down (through a "debugging procedure") where does this space come from.

 

I have already tried to get a "debug log" using \tracing commands, in this case \tracingpages, \tracingoutput and \tracingboxes. Then I use the following awk command (see also here) to search through the log:

$ awk '
{nrp=sprintf("[%5d]",NR);}
NR<=p {print nrp " :" $0} /^%%/ {print nrp "::" $0; p=NR+4} ;
/\\hbox|\\vbox|\\glue| box/ {print nrp "  " $0} ;
/\\OT1\/cmr\/bx\/n\/14.4 [Th]/ {print nrp "  " $0}
' test.log

[  283]::%% goal height=598.0, max depth=5.0
[  284] :% t=0.0 g=598.0 b=10000 p=0 c=100000#
[  285] :% t=43.90276 plus 1.86108 g=598.0 b=10000 p=0 c=100000#
[  286] :% t=55.90276 plus 1.86108 g=598.0 b=10000 p=0 c=100000#
[  287] :% t=67.90276 plus 1.86108 g=598.0 b=10000 p=100 c=100000#

[  298]  Completed box being shipped out [1]

[  299]  \vbox(676.36243+0.0)x373.0, direction TLT
[  302]  .\glue 23.0
[  303]  .\vbox(653.36243+0.0)x345.0, shifted 28.0, direction TLT
[  305]  ..\vbox(12.0+0.0)x345.0, glue set 5.55556fil, direction TLT
[  309]  ...\glue 0.0 plus 1.0fil
[  310]  ...\hbox(6.44444+0.0)x345.0, glue set 340.0fil, direction TLT
[  313]  ....\glue 0.0 plus 1.0fil
[  317]  ..\glue 18.06749
[  320]  ..\glue(\lineskip) 0.0
[**321]  ..\vbox(598.0+0.0)x345.0, glue set 434.09723fil, direction TLT
[**332]  ...\glue(\topskip) 0.00002
[**333]  ...\hbox(9.99998+2.79999)x345.0, glue set 253.16011fil, direction TLT
[  340]  ....\hbox(0.0+0.0)x0.0, direction TLT
[  343]  .....\glue 0.0
[  344]  ....\OT1/cmr/bx/n/14.4 T
[  345]  ....\OT1/cmr/bx/n/14.4 h
...
[ 1703]::%% goal height=598.0, max depth=5.0
[ 1704] :% t=0.0 g=598.0 b=10000 p=0 c=100000#
[ 1705] :% t=10.0 g=598.0 b=10000 p=-10001 c=-10001#
[ 1706] :%% goal height=598.0, max depth=5.0
[ 1706]::%% goal height=598.0, max depth=5.0
[ 1707] :% t=0.0 g=598.0 b=10000 p=0 c=100000#
[ 1708] :% t=10.0 g=598.0 b=10000 p=0 c=100000#
[ 1709] :% t=10.0 plus 1.0fil g=598.0 b=0 p=-10000 c=-10000#
[ 1710] :

[ 1712]  Completed box being shipped out [2]

[ 1713]  \vbox(676.36243+0.0)x424.0, direction TLT
[ 1716]  .\glue 23.0
[ 1717]  .\vbox(653.36243+0.0)x345.0, shifted 79.0, direction TLT
[ 1719]  ..\vbox(12.0+0.0)x345.0, glue set 5.55556fil, direction TLT
[ 1723]  ...\glue 0.0 plus 1.0fil
[ 1724]  ...\hbox(6.44444+0.0)x345.0, glue set 340.0fil, direction TLT
[ 1728]  ....\glue 0.0 plus 1.0fil
[ 1731]  ..\glue 18.06749
[ 1734]  ..\glue(\lineskip) 0.0
[ 1735]  ..\vbox(598.0+0.0)x0.0, glue set 588.0fil, direction TLT
[ 1740]  ...\glue(\topskip) 10.0
[ 1741]  ...\hbox(0.0+0.0)x0.0, direction TLT
[ 1745]  ...\glue 0.0 plus 1.0fil
[ 1748]  ...\glue 0.0
[ 1751]  ..\glue(\baselineskip) 25.29494
[ 1752]  ..\hbox(0.0+0.0)x345.0, direction TLT
...
[ 1756]::%% goal height=598.0, max depth=5.0
[ 1757] :% t=10.0 g=598.0 b=10000 p=-300 c=100000#
[ 1758] :% t=64.97215 plus 7.16663 minus 0.86108 g=598.0 b=10000 p=150 c=100000#
[ 1759] :% t=76.97215 plus 7.16663 minus 0.86108 g=598.0 b=10000 p=0 c=100000#
[ 1760] :% t=88.97215 plus 7.16663 minus 0.86108 g=598.0 b=10000 p=0 c=100000#

[ 1769]  Completed box being shipped out [3]

[ 1770]  \vbox(676.36243+0.0)x373.0, direction TLT
[ 1773]  .\glue 23.0
[ 1774]  .\vbox(653.36243+0.0)x345.0, shifted 28.0, direction TLT
[ 1776]  ..\vbox(12.0+0.0)x345.0, glue set 5.55556fil, direction TLT
[ 1780]  ...\glue 0.0 plus 1.0fil
[ 1781]  ...\hbox(6.44444+0.0)x345.0, glue set 340.0fil, direction TLT
[ 1784]  ....\glue 0.0 plus 1.0fil
[ 1788]  ..\glue 18.06749
[ 1791]  ..\glue(\lineskip) 0.0
[*1792]  ..\vbox(598.0+0.0)x345.0, glue set 459.0834fil, direction TLT
[*1796]  ...\glue(\topskip) 10.0
[*1797]  ...\hbox(0.0+0.0)x345.0, glue set 330.0fil, direction TLT
[*1804]  ....\hbox(0.0+0.0)x15.0, direction TLT
[*1809]  ....\glue(\parfillskip) 0.0 plus 1.0fil
[*1811]  ....\glue(\rightskip) 0.0
[*1816]  ...\glue 15.0694 plus 4.30554 minus 0.86108
[*1819]  ...\glue(\parskip) 0.0 plus 1.0
[*1822]  ...\glue(\baselineskip) 8.00002
[*1823]  ...\hbox(9.99998+2.79999)x345.0, glue set 132.72354fil, direction TLT
[ 1830]  ....\hbox(0.0+0.0)x0.0, direction TLT
[ 1833]  .....\glue 0.0
[ 1834]  ....\OT1/cmr/bx/n/14.4 T
[ 1835]  ....\OT1/cmr/bx/n/14.4 h

I've isolated relevant sections of the log above - and the lines that differ in the box construction, right before the first "Th" letters of each \section* start being typeset, are indicated with * before the line number (for that, I removed the leading line numbers, and compared the two snippets with meld).

The \tracingpages log (as much as I can read it) tells me that:

  • pg 1 starts at top 0.0, penalty 0 (% t=0.0 g=598.0 b=10000 p=0 c=100000#)
  • pg 3 starts at top 10.0, penalty -300 (% t=10.0 g=598.0 b=10000 p=-300 c=100000#)

... yet, the \tracingboxes log shows that, in spite of this, the initial hierarchy of output boxes is the same for both cases, until this point is reached:

  • pg 1: ..\vbox(598.0+0.0)x345.0, glue set 434.09723fil, direction TLT
  • pg 3: ..\vbox(598.0+0.0)x345.0, glue set 459.0834fil, direction TLT

... and I cannot see how the top difference of 10.0-0.0 = 10.0 in the first case, would add up to 459.0834-434.09723 = 24.9862 (ignoring the fact that pg3 has additional boxes and glues) ??

In essence, it is clear that it is something in the path of the custom biblatex citation command that causes this vertical space on top - but how could the page/box building log be used, to find the exact command which is causing this? Or is a different debugging approach needed altogether?

share|improve this question

2 Answers 2

up vote 3 down vote accepted

Tracing here is best done at the macro level: I'd load the trace package and use \traceon/\traceoff. If you load the trace package and do

\traceon \myCite{vangennep}

the start of the (rather long) long is

\myCite ->\blx@citecmdinit \@ifstar {\blx@citepunct {\blxcitecmd {myCite*}}} {\
blx@citepunct {\blxcitecmd {myCite}}}

\blx@citecmdinit ->\blx@leavevmode@cite \iftoggle {blx@bibliography} {} {\blx@i
nitunit }

\blx@leavevmode@cite ->\ifhmode \ifnum \spacefactor =\blx@sf@par \else \spacefa
ctor \@m \fi \else \leavevmode \fi 
{\ifhmode}
{false}

\leavevmode ->\unhbox \voidb@x 

thus showing that citations are horizontal mode commands. That's where the issue is, as \section and similar expect to start new paragraphs. You'll see the same spacing issue as the example with

\leavevmode
\section*{foo}

as again we have an 'empty' paragraph followed by a section.

I'd say the solution here is to create a simple \myCite definition using \newcommand, as it's not a 'normal' citation at all as far as biblatex is concerned.

share|improve this answer
    
Thanks a million for this answer, @JosephWright - I must admit, I have tried the \traceon, have even suspected the \leavevmode, but was lacking crucial piece of info: "horizontal mode commands... (vs.) \section and similar expect to start new paragraphs" Thus, I thought I could confirm through an intermediate way - just by tracing the pages' construction. But it turns out, without the awareness of what \leavevmode \section*{foo} does, I could have hardly gotten any further. Many thanks again - cheers! –  sdaau Jul 3 '12 at 9:25

Just as an addendum: here is how the modified MWE looks, where a \myCiteNcmd command has been implemented via \newcommand, as per @JosephWright's answer:

\documentclass[twoside,a4paper]{book}

\usepackage{lua-visual-debug}
\usepackage{lipsum}
\usepackage{biblatex}
\addbibresource{biblatex-examples.bib}
\usepackage{trace}


\newbibmacro*{myCite}{%
\section*{The title: \printfield{title}} %
}

\DeclareCiteCommand{\myCite}%
{}%
{%
\usebibmacro{myCite}}%
{}%
{}%


\makeatletter
\newcommand{\myCiteNcmd}[1]{%
  \def\blx@loopcode{\usebibmacro{myCite}} %
  \def\blx@precode{} % also needed
  \def\blx@postcode{\blx@postpunct} % also needed
  \def\blx@dlimcode{} % also needed, but only for multiple (comma-sep) "cites"
  \blx@blxinit % also needed (inits \printfield)
  \blx@citeloop{#1} %
}
\makeatother


\def\tracingboxes{\showboxbreadth = \maxdimen
  \showboxdepth = \maxdimen}%


\begin{document}

\tracingpages=1 % pages
\tracingoutput=1 % boxes
\tracingboxes

\section*{Thesting one}

\lipsum[1]

\cleardoublepage


\traceon
% \myCite{vangennep}   % the "old" command - biblatex custom cite
\myCiteNcmd{vangennep} % \newcommand
\traceoff

% note: multiple "citations" will pass OK,
% however, there is a new \section* added for each "citation"!
% \myCiteNcmd{vangennep,knuth:ct}

\lipsum[2]

\end{document}

The above finally shows both \sections* being aligned all the same at the top of the page (and it works by calling the same \usebibmacro as previously, and even when it uses the unexpandable \printfield command from biblatex).

Note that here one needs to be careful to pass the citation entry keys to the \biblatex formatter - as most of the "front end" \biblatex command do not, in fact, use them (given that there is implied looping in \DeclareCiteCommand).

So, what I did was simply to observe the \traceon debug log (for the custom biblatex \myCite), and find that it is essentially executed via:

...
\blx@citei@myCite #1#2#3#4->\ifblank {#1} {} {\def \abx@field@prenote {#1}}\ifb
lank {#2} {\let \blx@thenotecheck \relax } {\def \abx@field@postnote {#2}}\def
\blx@precode {}\def \blx@loopcode {\usebibmacro {myCite}}\def \blx@dlimcode {}\
def \blx@postcode {#4}\blx@citeloop {#3}\endgroup
#1<-
#2<-
#3<-vangennep
#4<-\blx@postpunct
...

Here it is obvious that the entry key is handled by \blx@citeloop. So, I copied all relevant stanzas from here into \myCiteNcmd - and beyond that, only needed \blx@blxinit to define \printfield itself.

Hope this helps someone - cheers!

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.