这又是在可重构(且简单)的示例中很难捕捉的行为之一,因此必须借助于动画。
基本上,问题是这样的:波浪号 ( ~
) 应该是一个不间断的空格字符,对吧?那么,为什么当我Fig.~\ref{fig:myfigure}
在下面的 MWE 中使用时,它有时会断行确切地在该~
角色的位置,如下面的 .gif 所示:
例如,第 41 帧最终如下所示(单击可查看完整分辨率):
这难道不是波浪号所要阻止的吗?
Fig.~\ref{...}
我怎样才能找出发生这种情况的原因 - 以及如何在我的构造中获得不间断的空间?
下面是 MWE,它使用了我发布的test-tilde.tex
包repeat-build.sty
这里(目前仅在 Linux 上测试) - 并且需要构建两次,使用-shell-escape
:
pdflatex -shell-escape test-tilde.tex # first time, refs wrong here
pdflatex -shell-escape test-tilde.tex # second time, refs ok (can enable the `convert` post action if desired)
...这样就生成了上面动画中使用的所有 PDF。
编辑:我修改了代码,因此它将在没有的情况下构建repeat-build.sty
;并且它将重建上面静止屏幕截图上的情况(其中变量\tester
= 87);然后如果您想使用repeat-build
,只需(取消)注释相应的行。
代码如下:
\documentclass[%
12pt,
journal,
onecolumn,
twoside,
draftcls,
letterpaper,
]{IEEEtran}
\usepackage[demo]{graphicx} %
\usepackage{xcolor} % \pagecolor
\pagecolor{yellow!15}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}
\usepackage[nopar]{lipsum}
\usepackage{xstring}
% https://tex.stackexchange.com/a/26808/2595
\makeatletter
\def\unpacklipsum#1#2#3{%
\count@=#1\relax
\advance\count@\m@ne
\def#3{}%
\loop\ifnum\count@<#2\relax
\advance\count@\@ne
\edef#3{#3\csname lipsum@\romannumeral\count@\endcsname}%
\repeat}
% https://tex.stackexchange.com/a/168754/2595
\def\loremnchars[#1]#2{%
\unpacklipsum{#1}{#1}{\myunpacked}%
\StrMid{\myunpacked}{1}{#2}% same as \StrLeft{\myunpacked}{#2}
}
\def\eloremnchars#1#2#3{%
\unpacklipsum{#1}{#1}{\myunpacked}%
% \StrMid is not an expandable macro (can't go in \def) - but
% can "return" by saving in #3
\StrMid{\myunpacked}{1}{#2}[#3]
}
\def\getLoremParaNumChars#1#2{%
\unpacklipsum{#1}{#1}{\myunpacked}%
\StrLen{\myunpacked}[#2]
\typeout{Lorem paragraph #1 has #2 characters}.
}
\makeatother
\usepackage[format=plain,font=small,skip=12pt]{caption} %
\usepackage{listings} %
\usepackage{units} %
\usepackage{floatrow}
\floatsetup[figure]{capposition=bottom}
\usepackage{etoolbox}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{tikz}
\usetikzlibrary{shapes,positioning}
\usetikzlibrary{fit}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.markings}
\usepackage{txfonts} % Times font in math; tlmgr install txfonts
\renewcommand{\ttdefault}{pcr}
\usepackage[UTF8]{ctex} % needs simsun.ttc in same directory
\usepackage{setspace}
\usepackage{siunitx}
\usepackage[american]{babel}
\usepackage{csquotes}
\makeatletter
\let\l@AMERICAN\l@american % https://tex.stackexchange.com/q/88861/
\makeatother
\usepackage[style=ieee,isbn=true,doi=false,url=true,backend=biber]{biblatex}
% here, set the \tester at a number,
% so we don't hit an error if we
% compile without repeat-build (-shell-escape)
% https://tex.stackexchange.com/a/185976/2595
%%%% uncomment the below part if you want to use {repeat-build}:
% \ifx\tester\undefined{%
% \global\protected\def\tester{100} %
% }\fi
% % do not rm the .aux here; need them for fig label;
% % since the process needs to run twice for correct
% % label - comment the convert post action.
% %% manual convert command:
% %% convert -verbose -density 150 test-tilde-*.pdf[0] -crop 1024x580+137+773 -resize 512x +repage -delay 15 -loop 0 test-tilde.gif
% %% gifsicle -O2 test-tilde.gif -o test-tilde-O2.gif # helps reduce size
% \def\pacode{%
% pwd; %
% ls \jobname-*.log \jobname-*.aux; %
% rm -vrf \jobname-*.log ;% \jobname-*.aux; %
% % convert -verbose -density 75 \jobname-*.pdf[0] %
% % -crop 512x290+68+386 %
% % +repage %
% % -delay 15 -loop 0 % -delay 5
% % \jobname.gif %
% % ; %
% % eog \jobname.gif ; % run viewer
% }
% \usepackage[%
% vartoken=\tester,% % loop the variable token: \tester
% varvals={15,16,...,29,41,42,...,52,58,59,...,65,77,78,...,89},% set \tester to change; (was from 0 to 100 {0,...,100})
% postactioncode={\pacode},%
% ]{repeat-build}
% \unprotect\tester
% \makeatletter
% \def\getrjname{\rpbuild@jobname}
% \makeatother
%%%% else this should be enough for a usual run:
\def\tester{83} % comment this if using repeat-build!
\begin{document}
\title{Test title}
\author{test}
\maketitle
\begin{abstract}
The abstract text goes here.
\end{abstract}
\section{Test section}
Test text, before figure:
\setcounter{figure}{22} % if 10, then {figure} becomes 11
\begin{figure}[h!t]
\singlespacing
\includegraphics[width=\textwidth,height=100pt]{demo.whatever}
%\caption[shortdesc]{The figure is being shown here. \protect\loremnchars[3]{255}}
\captionof{figure}[shortdesc]{The figure is being shown here. \protect\loremnchars[3]{255}}
\label{fig:myfigure}
\end{figure}
Current: doc: \jobname; \verb!\tester!: \tester ... \loremnchars[1]{150}
\eloremnchars{2}{\tester}{\tretA} %
\pgfmathtruncatemacro{\tB}{\tester/2} %
\eloremnchars{4}{\tB}{\tretB} %
\eloremnchars{5}{\tester}{\tretC} %
\tretA\space on Fig.~\ref{fig:myfigure}.
\tretB\space on Fig.~\ref{fig:myfigure},
\tretC\space on Fig.~\ref{fig:myfigure}.
\loremnchars[3]{712}.. And ... \lipsum[7]
%\getLoremParaNumChars{3}{\tret} %\typeout{\tret}
%\eloremnchars{3}{712}{\tret} \typeout{\tret}
\end{document}
答案1
以下是问题中缺少的 MWE:
\documentclass[12pt,onecolumn,draftcls]{IEEEtran}
\usepackage{ctex}
\begin{document}
%\show~
Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi.
Morbi auctor \space on Fig.~23. Quisque ullamcorper placerat ipsum.
Cras \space on Fig.~23, Fusce mauris. Vestibulum luctus nibh at lectus. Sed
bibendum, nulla a faucibus semp \space on Fig.~23.
\end{document}
取消注释\show~
告诉我们
> ~=macro: ->\hspace {0.25em plus 0.125em minus 0.08em}\ignorespaces . l.4 \show~
即可破坏空间,删除该\usepackage{ctex}
线会将其恢复到正常状态
> ~=macro: ->\nobreakspace {}. l.4 \show~
如果必须使用,ctex
那么似乎您可以用~
来替换\nbs
,或者您可以使用\standardtilde
来恢复 的通常行为~
。
答案2
只是想在这里包含一些有关我的调试过程的注释。
显然,由于波浪号是问题所在,我首先想看看它到底起什么作用。起初,我甚至不认为它是一个宏(我猜我以为它“只是”一个带有“特殊 catcode”的字符),然后我想texdef
在控制台 shell 中尝试一下:
$ texdef -t latex '~'
\~:
macro:->\OT1-cmd \~\OT1\~
好的,事实证明,它可能是一个宏......但这不是我正在寻找的宏:texdef
自动添加一个反斜杠,所以我们实际看到的是宏的定义(反斜杠波浪号),而不是(波浪号)\~
的定义。~
此时,事情变得复杂了,因为很难在线搜索;波浪号是 ASCII 字符(因此它没有 html 实体表示,经 确认php -r 'echo htmlentities("a~a\n",ENT_COMPAT,"UTF-8");'
)- 因此,我无法真正搜索查询,\def ~
无论是在线搜索还是 Tex.SE 上的本地搜索。不过,不知何故,我在在线搜索结果中注意到了这一点:
... )\textasciitilde 是 latex 的标准部分(在文件 latex.ltx 中)。...
啊,至少有一个指针;所以现在可以从终端 shell 执行此操作:
$ kpsewhich latex.ltx
/path/to/texlive/2011/texmf-dist/tex/latex/base/latex.ltx
$ grep '~' $(kpsewhich latex.ltx) | grep def
\chardef\active=13 \catcode`\~=\active % tilde is active
\def~{\errmessage{%
\def~{\typeout{! %
\def~{\nobreakspace{}}
\lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1}}}
此外,我还偶然发现https://tex.stackexchange.com/a/59260/2595和https://tex.stackexchange.com/a/66951/2595- 这对我来说证实了 tilde 作为宏的原始定义是\def~{\nobreakspace{}}
。
好的,那现在怎么办?好吧,首先我想重新定义 tilde,这样它就会将消息打印到 stdout;所以我想,如果它被某个东西替换,那么打印就会停止,并指向重新定义发生的位置。所以我用了这个:
% should stop when something changes its def...
\newcounter{tildcount}
\typeout{tilde MEANING AT START: \meaning~ }
% tilde MEANING AT START: macro:->\nobreakspace {}
\let\origtilde~
\def~{%
\stepcounter{tildcount}%
% \meaning~ remains the same as before, as long as
% this \def is in place; so don't print it.
\typeout{tilde called \thetildcount\space times}%
\origtilde%
}
到目前为止一切顺利 - 除了这个宏可能会在标题内的波浪号等上崩溃。更糟糕的是,重新定义不会发生在文档中间,所以这最终没有多大帮助。
因此,唯一剩下的事情就是打印\meaning~
整个文档(包括序言),并查看其中的变化。所以我做了与此相当的事情(如上所示test-tilde.tex
):
% https://tex.stackexchange.com/questions/81789/get-current-source-line-number/81794#81794
\def\showLineMean{\typeout{line \the\inputlineno; MEANING: \meaning~}}
...
\usetikzlibrary{calc} \showLineMean % l.61
\usetikzlibrary{decorations.markings} \showLineMean % l.62
\usepackage{txfonts} \showLineMean % Times font ... % l.63
\renewcommand{\ttdefault}{pcr} \showLineMean % l.64
\usepackage[UTF8]{ctex} \showLineMean % simsun.ttc ... % l.65
\usepackage{setspace} \showLineMean % l.66
\usepackage{siunitx} \showLineMean % l.67
\usepackage[american]{babel} \showLineMean % l.68
\usepackage{csquotes} \showLineMean % l.69
...
\usepackage[style=ieee,...]{biblatex} \showLineMean % l.73
...
\showLineMean % l.115
\begin{document} % l.116
\showLineMean % l.117
\title{测试标题} ...
然后可以这样:
$ pdflatex test-tilde.tex # ...
$ grep MEANING test-tilde.log
line 61; MEANING: macro:->\nobreakspace {}
line 62; MEANING: macro:->\nobreakspace {}
line 63; MEANING: macro:->\nobreakspace {}
line 64; MEANING: macro:->\nobreakspace {}
line 65; MEANING: macro:->\nobreakspace {}
line 66; MEANING: macro:->\nobreakspace {}
line 67; MEANING: macro:->\nobreakspace {}
line 68; MEANING: macro:->\active@prefix ~\active@char~
line 69; MEANING: macro:->\active@prefix ~\active@char~
line 73; MEANING: macro:->\active@prefix ~\active@char~
line 115; MEANING: macro:->\active@prefix ~\active@char~
line 117; MEANING: macro:->\hspace {0.25em plus 0.125em minus 0.08em}\ignorespa
哈哈!所以波浪符号在加载~
时第一次改变babel
- 然后,紧接着第二次改变\begin{document}
!
当然,我看不出这背后的任何逻辑——作为最后的手段,我尝试在互联网上查找最后一个含义(在文档编写期间有效的含义);幸运的是,最先找到的结果之一是:
这是 CJK 宏包 ver. 4.8.3 的命令文件 command.txt ...
\CJKtilde 此命令将活动“~”字符的定义从不可断开的空格更改为 \def~{\hspace{0.25em plus 0.125em minus 0.08em}}
嗯,这最终证实了问题是什么(并且解决方案与接受的答案相同)。
然而,有些令人难过的是 - 经过这一切,我不能说这是一个我只能在本地机器上完成的调试过程,而无需在线查找......希望我的程序比这更强大:)
好吧,希望这对某人有帮助,
干杯!