调试页面顶部的垂直空间(自定义 biblatex cite 命令内的部分)?

调试页面顶部的垂直空间(自定义 biblatex cite 命令内的部分)?

请考虑以下用lualatex test.tex(++ bibtex test)编译的 MWE 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}

在其中,我有一个直接\section*在页面顶部调用的 - 以及一个\section*通过自定义引用命令在页面顶部调用的(\myCite通过包功能实现biblatex)。(两个部分都以“Th”开头,所以我有一个用于调试的标记)

问题在于这两个\section*s 没有“对齐” - 即,它们不是从相同的垂直位置开始(通过 生成的图像
montage -density 150 -bordercolor LimeGreen -border 1 test.pdf[0] test.pdf[2] -geometry +2+2 -tile 2x1 out.png
)​​:

出.png

换句话说,\section*被调用的 via\myCite在页面顶部有一些额外的垂直空间。而且由于(显然)不能只重置页面顶部的垂直空间(尤其是不是通过调用内部“命令代码”) - 我想知道:

  • 这个垂直空间从何而来?
  • 如何消除它?

特别是,我感兴趣的是以某种方式追踪(通过“调试程序”)这个空间来自哪里。

 

我已经尝试使用以下方法获取“调试日志”\跟踪命令在本例中\tracingpages\tracingoutput\tracingboxes。然后我使用以下awk命令(也可以看看这里)搜索日志:

$ 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

我已经隔离了上述日志的相关部分 - 并且在框构造上有所不同的行,就在正在排版的每个开头的第一个“Th”字母之前,在行号前\section*用 表示(为此,我删除了前导行号,并将两个片段与 进行比较)。*meld

\tracingpages日志(据我所知)告诉我:

  • 第 1 页从顶部 0.0 开始,惩罚 0 ( % t=0.0 g=598.0 b=10000 p=0 c=100000#)
  • 第 3 页从前 10.0 开始,惩罚 -300 ( % t=10.0 g=598.0 b=10000 p=-300 c=100000#)

...然而,\tracingboxes日志显示,尽管如此,两种情况下输出框的初始层次结构是相同的,直到达到这一点:

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

... 并且我看不出第一种情况下 10.0-0.0 = 10.0 的最高差异如何加起来等于 459.0834-434.09723 = 24.9862(忽略 pg3 有额外的盒子和胶水的事实)??

本质上,很明显,自定义引用命令路径中的某些东西biblatex导致了顶部出现垂直空间 - 但如何使用页面/框构建日志来查找导致这种情况的确切命令?还是需要完全不同的调试方法?

答案1

最好在宏观层面上进行跟踪:我会加载trace包并使用\traceon/ \traceoff。如果你加载跟踪包并执行

\traceon \myCite{vangennep}

(相当长的)长的开始是

\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 

这表明引用是水平模式命令。这就是问题所在,因为\section和类似的期望开始新的段落。您将看到与示例相同的间距问题

\leavevmode
\section*{foo}

因为我们再次有一个“空”段落,后面跟着一个部分。

我想说这里的解决方案是\myCite使用创建一个简单的定义\newcommand,因为就而言,它根本不是一个“正常”的引用biblatex

答案2

仅作为附录:这是修改后的 MWE 的样子,其中\myCiteNcmd命令已通过 实现\newcommand,按照@JosephWright 的回答

\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}

上面最终显示两者\sections*在页面顶部全部对齐(并且它通过调用\usebibmacro与之前相同的方法工作,即使它使用了\printfield来自的不可扩展命令biblatex)。

请注意,这里需要小心地将引文输入键传递给\biblatex格式化程序 - 因为大多数“前端”\biblatex命令都是这样做的不是,事实上,使用它们(假设中有隐含的循环\DeclareCiteCommand)。

因此,我所做的只是观察\traceon调试日志(针对自定义biblatex \myCite),并发现它基本上是通过以下方式执行的:

...
\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
...

这里很明显,输入键由 处理\blx@citeloop。因此,我将这里所有相关的节复制到\myCiteNcmd- 除此之外,只需要\blx@blxinit定义\printfield自身。

希望这对某人有帮助 - 干杯!

相关内容