请考虑以下用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
):
换句话说,\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
自身。
希望这对某人有帮助 - 干杯!