我很惊讶地从 复制了一个字符(我花了很多时间来修剪周围的空格),结果\vbox
却发现只要它在文本前面(在同一行),它就会强制换行。下面是一个简化版本,它会产生相同的结果。我需要@
出现在 的同一行上hello world
,而不需要将两者都放在 中\hbox
(这是我发现的唯一可行的方法,但由于设计问题,我无法在原始代码中仅使用hello world
--only @
-- 来包含它们)。
PS 让我们将解决方案限制为在 XeLaTeX 中编译的纯 TeX 代码。
\documentclass[border=5mm,varwidth]{standalone}
\usepackage{color}
\pagecolor{black}
\color{white}
\begin{document}
\newbox\zT
\setbox\zT\vbox{\makeatletter@\makeatother}
\copy\zT hello world\par % try 1 (failed)
\hbox{\copy\zT}hello world % try 2 (failed)
\end{document}
预期产出(近似值):
答案1
PS 让我们将解决方案限制为在 XeLaTeX 中编译的纯 TeX 代码。
您的示例中没有使用在纯 TeX 中定义的命令,纯 TeX 有一个\newbox
命令,但定义完全不同,并且其他命令都不是纯 TeX 中定义的命令,它们要么是 LaTeX 命令,要么是 TeX 原语。
你还没有说你想做什么,但是 LaTeX 框命令旨在避免这样的问题(并且\setbox
在加载颜色后使用 tex 原语特别危险,你很容易生成无效的 PDF 输出而没有任何警告)
LaTeX 标记为
\documentclass[border=5mm,varwidth]{standalone}
\usepackage{color}
\pagecolor{black}
\color{white}
\begin{document}
\newsavebox\zT
\sbox\zT{@}
\usebox{\zT} hello world
\end{document}
要查看原始注释中的问题,请注意,方框不会启动段落,因此在以下任一情况下,
\vbox{...}
Hello World
或者
\hbox{...}
Hello World
段落从H
开始,框内容位于段落之前(即上方)。
通常的解决方案是\leavevmode
在框前使用来开始段落所以\leavevmode\hbox{@}
或更好\mbox{@}
或使用框寄存器,\leavevmode\copy\zT
或更好\usebox{\zT}
。
但在你的情况下,盒子无论如何都放不下左边,H
因为你有
\vbox{@}
因此,这是在 vmode 内开始一个段落,因此段落文本(\indent
框@
和\parfillskip
)将被换行到宽度为的行\hsize
,因此 vbox 内容包括\hbox
宽度为的\hsize
(即\textwidth
)而不仅仅是@
。
TeX 可以向您显示由以下方式构造的框\vbox{@}
:
\documentclass[border=5mm,varwidth]{standalone}
\usepackage{color}
\pagecolor{black}
\color{white}
\begin{document}
\showoutput
\setbox\zT\vbox{@}
\showbox\zT
\end{document}
生产
\vbox(6.94444+0.0)x345.0
.\hbox(6.94444+0.0)x345.0, glue set 337.2222fil
..\hbox(0.0+0.0)x0.0
..\OT1/cmr/m/n/10 @
..\penalty 10000
..\glue(\parfillskip) 0.0 plus 1.0fil
..\glue(\rightskip) 0.0
因此 vbox 包含一个宽度为零的 hbox,\hsize
其中包含一个大小为零的空 hbox(用于段落缩进)、@ 字符和\parfillskip
粘合\rightskip
节点。
答案2
如果您想使用纯 TeX,请不要在 LaTeX 中嵌入内容。
从你的帖子中我猜测您想要修剪某个字符周围的空白。例如,以 为例\times
。
这是周围没有空白的字符,周围的细线框只是为了显示边界框。
如果要使用剪切的字符,可以将其设置到一个框中,然后\copy
将该框设置好,但是记住命令\copy
不会从垂直模式变为水平模式。
\newbox\btimesbox
% remove the white space on the left and on the right
\setbox\btimesbox=\hbox{\kern-0.35ex$\times$\kern-0.35ex}
% remove the white space at the bottom
\setbox\btimesbox=\hbox{\raise-0.03ex\box\btimesbox}
% we want the depth to be zero
\dp\btimesbox=0pt
% remove the white space at the top
\ht\btimesbox=1.1ex
\def\btimes{\leavevmode\copy\btimesbox}
\btimes\ hello world
t\btimes t
t$\times$t
\bye
答案3
它不起作用,因为 a\vbox
总是自动具有宽度\hsize
,即整个文本块的宽度。您可以执行类似操作\vbox{\hsize=1em...}
,但这只是无稽之谈,因为有更好的解决方案。
我向你提出三项建议。
在 里面定义一个宏
\makeatletter...other
,这样会冻结 宏里面的 catcode@
,所以用宏排版@
不会受到周围 catcode 的影响。\makeatletter \newcommand*\letterat{@} \makeatother
定义一个字符常量。这将在您提供的代码处插入字符。Catcodes 不适用于字符常量。缺点是这会占用一个寄存器,但如今有了 e-TeX,这实际上不是问题。
\chardef\letterat=`\@
将字符放入水平盒子中。这有几个缺点。首先,字符根本不适应周围的字体,其次,它还需要一个寄存器,第三,它不能放在前导码中,因为必须在分配盒子时加载字体。
\newbox\atbox \setbox\atbox=\hbox{@} \newcommand*\letterat{\leavevmode\unhcopy\atbox}