% -*- coding: utf-8 -*- % This is part of the book TeX for the Impatient. % Copyright (C) 2003 Paul W. Abrahams, Kathryn A. Hargreaves, Karl Berry. % See file fdl.tex for copying conditions. % 中文翻译 by Zhaopeng Xing (zpxing@gmail.com) \input macros %\chapter{Tips and techniques} \chapter{建议和技巧} \chapterdef{tips} % \TeX\ is a complex program that occasionally works its will in % mysterious ways. In this section we offer some tips on solving % problems that you might encounter and explain some handy techniques. \TeX{} 是一个复杂的程序,偶尔地会以你看不懂的方式变得不听话。这一章, 我们提供一些解决问题的小贴士并阐释一些有用的技巧。 %\section Correcting bad page breaks \section 纠正不良分页 % \bix^^{page breaks//bad} % Sometimes \TeX\ breaks a page right in the middle of material that you % want to keep together---for example, % a section heading and the text that follows it, % or a short list of related items. There are two ways to correct the % situation: % \ulist\compact % \li You can force the material to be kept together. % \li You can force a page break at a different place. % \endulist \bix^^{分页//不良分页} 有时,\TeX{} 在你想要放在一起的素材中间分页——例如,章节标题和随后的文 本,或者一个互有联系的项目列表。有两种校正方法: \ulist\compact \li 强制素材被放在一起。 \li 在别的地方要求分页。 \endulist % The simplest way to force \TeX\ to keep material together on a page is % to enclose the material in a vbox using the |\vbox| command \ctsref{\vbox}. % ^^|\vbox//fixing page breaks with| % A vbox is ordinarily better than an hbox for this purpose because most % often the material to be kept together, % e.g., a sequence of paragraphs, will be vertical mode material. % You should % precede and follow the vbox by an implicit or explicit paragraph command % (either a blank line or |\par|); otherwise % \TeX\ may try to make the vbox part of an an adjacent paragraph. % The vbox method has an important limitation: % you can't apply it to portions of text smaller than a paragraph. 要强制 \TeX{} 把素材放在同一页上,最简单的办法是 使用 |\vbox| 命令\ctsref{\vbox}来使素材被封装在一个竖直盒子里。 ^^|\vbox//用它修正分页| 这里使用竖直盒子比水平盒子要好,因为大多数情况下, 需要放在一起的是竖直模式素材,比如连续的段落。 竖直盒子的前后,你都要放一个隐含或明显的分段命令(或者空行,或者 |\par|); 否则的话,\TeX{} 会试图使竖直盒子成为相邻段落的一部分。 竖直盒子的方法有一个重要的局限:不能用于不足一个段落的小部分文本。 % You can sometimes keep the lines of a single paragraph together by enclosing % the paragraph in a group and assigning |\interlinepenalty| % \ctsref{\interlinepenalty} % a value of $10000$ at the start of the group (or elsewhere before the % end of the paragraph). % This method causes \TeX\ to consider page breaks within that paragraph to be % infinitely undesirable. % However, if all the page breaks that \TeX\ can find are infinitely undesirable, % it may break the page within the paragraph anyway. 有时候,要把一个自然段的各行放置在一起,你可以把它封装在一个编组中,并 在编组开始的地方(或者段落结束前的其它位置)令 |\interlinepenalty|% \ctsref{\interlinepenalty}的值为 $10000$。这样就告诉了 \TeX{},“绝对不 能”在段内分页。但是,如果 \TeX{} 发现所有要分页的地方都是“绝对不能”的, 它可能不管三七二十一,就在自然段里分页。 % A ^|\nobreak| command (\xref{vnobreak}) % after the end of a paragraph prevents \TeX\ % from breaking the page at the following item % (unless that item happens to be a penalty of less than $10000$). % This is also the best way to prevent a page break after a heading, % since a heading usually behaves like a paragraph. % The |\nobreak| must follow the blank line or |\par| that ends % the paragraph so that \TeX\ won't treat the |\nobreak| as part of the % paragraph. % For the |\nobreak| to be effective, it must also come before % any legal breakpoint at the end of the paragraph. % The glue that \TeX\ inserts % before the next paragraph is such a breakpoint, % and so is any vertical glue that you insert explicitly after a paragraph. % Thus the |\nobreak| should usually be % the very first thing after the end of the paragraph or heading. 在段落之后使用 ^|\nobreak| 命令 (\xref{vnobreak}) 会阻止 \TeX{} 在下一 项内容之前分页(除非下一项恰好是一个小于 $10000$ 的 惩罚项)。这也是防 止在章节标题之后分页的最佳方案,因为章节标题通常类似于一个自然段落。 |\nobreak| 需要放在段落结束的空行或者 |\par| 之后,从而避免 \TeX{} 将 |\nobreak| 作为段落的一部分处理。 |\nobreak| 还需要出现在段落末尾所有 适合分页的断点之前才有效。\TeX{} 插入在下一个段落之前的粘连就是这样的 一个断点,其他的还有你明确插入在段落后面的任何竖直粘连。 因 此,|\nobreak| 通常出现在段落或者标题结束之后的第一个位置。 % You can use the ^|\eject| command \ctsref{\eject} % to force \TeX\ to break a page at a % particular place. Within a paragraph, you can use the combination % `|\vadjust{\vfill\eject}|' % \ctsref{\vadjust} % ^^|\vadjust| % to force a break after the next complete output line. % The reason for preceding |\eject| by ^|\vfill| % \ctsref{\vfill} is to % get \TeX\ to fill out the page with blank space. % However, using |\eject| to fix page break problems % has a major disadvantage: % if the page boundaries in your document change, % the page breaks that you've inserted may no longer be where you want them. 你可以使用 ^|\eject| 命令\ctsref{\eject},强制 \TeX{} 在特定的地方分 页。在段落内部,你可以使用一个组合:`|\vadjust{\vfill\eject}|' \ctsref{\vadjust} ^^|\vadjust| 在下一行之后强制断开。|\eject| 之前 ^|\vfill| \ctsref{\vfill} 的作用是让 \TeX{} 使用空白来填充页面。但是,使用 |\eject| 来纠正分页问题的主要缺点在于:如果文档的页边距改变,分页的地 方可能未必就如你所愿那样。 % If you don't provide \TeX\ with a |\vfill| command to fill out the page % after an |\eject|, % \TeX\ redistributes the extra blank space as best it can and then usually % complains that ``an % underfull |\vbox| (badness $10000$) has occurred while |\output| is active.'' % You may encounter a similar problem with % any of the methods mentioned above for enclosing % material that you want to keep together. 如果你没有在 |\eject| 之后\footnote{译注:疑为笔误,应该是“之前”。}使用 |\vfill| 命令, \TeX{} 将尽其所能地重新分配额外的空白间距,然后 发牢骚:“an underfull |\vbox| (badness $10000$) has occurred while |\output| is active.”上面讲的封装素材在一起的任一方法中,类似的问题也会出现。 % The ^|\filbreak| command \ctsref\filbreak{} % \xrdef{filbreak} % provides a way of keeping the lines of one or more paragraphs % (or other vertical mode material) together on % a page. If you enclose a paragraph in |\filbreak|s, \TeX\ will effectively % ignore the |\filbreak|s if the paragraph fits on the current page and % break the page before the first |\filbreak| if the paragraph doesn't fit. % If you put |\filbreak|s around each paragraph in a sequence of paragraphs, % like this: % {\obeylines\display{ % {\tt \\filbreak} % \ % {\tt \\filbreak} % \ % {\tt \\filbreak} % \leavevmode\indent\vdots % \ % {\tt \\filbreak} % }} % \vfil\eject % \noindent % \TeX\ will keep the lines of each paragraph together on a page. % If \TeX{} breaks a page at a |\filbreak|, it will fill the bottom of the % page with blank space. ^|\filbreak| 命令 \ctsref\filbreak{} \xrdef{filbreak} 提供了一种方式来把一个自然段或几个段落(或者其他竖直模式素材)放在同一 页面上。当你用 |\filbreak| 来封闭一个自然段的时候,如果段落内容可以放 置在一页, \TeX{} 会有效地忽略那些 |\filbreak|;如果不是,\TeX{} 将在 第一个 |\filbreak| 之前分页。如果在连续段落中,每个自然段前后都有 |\filbreak|,比如这样: {\obeylines\display{ {\tt \\filbreak} \ {\tt \\filbreak} \ {\tt \\filbreak} \leavevmode\indent\vdots \ {\tt \\filbreak} }} \vfil\eject \noindent \TeX{} 将使每一段都是同页。如果在 |\filbreak| 处分页, \TeX{} 将用空白 填充页面底部。 % Sometimes you can get \TeX\ to modify the length of a page by changing % the ^|\looseness| parameter \ctsref\looseness{} for one or more paragraphs. % Setting |\looseness| negative within a paragraph causes \TeX\ to try to squeeze % the paragraph into fewer lines; setting it positive causes \TeX\ to try to % expand the paragraph into more lines. The disadvantage of changing |\looseness| % is that the interword spacing in the affected region won't be optimal. % You can get further information about \TeX's attempted line breaks by % setting |\tracingpages| (\xref\tracingpages) to $1$. 有时,你可以改变一个或几个段落的 ^|\looseness| 参数\ctsref{\looseness}% 以修改页面的长度。设置 |\looseness| 为负会让 \TeX{} 试图缩减段落的行数; 为正则增加其行数。改变 |\looseness| 的缺点在于:受影响区域的单词间距不是最佳的。 要了解更多的断行信息,可以设置 |\tracingpages|(\xref\tracingpages )为 $1$。 % \section Preserving the end of a page \section 保留页尾 % Sometimes you need to modify something on a single page and you want to avoid % reprinting the entire document. If your modification doesn't % change the page length too much, there's hope. You need to fix the end % of the page so that it falls in the same place; % the methods are similar to the ones for fixing a bad page break. 有时你需要在单个页面上修改某些地方但是又不想重排全部文档。如果页面长度 没有因为修改而改变很多,那就可以实现。你要做的是固定页面的尾部不 变,所需的办法跟纠正不良分页那里一样。 % If the original end of page came between paragraphs, you can % force a page break at the same place % using any of the methods we've described above. Otherwise, % you must force \emph{both} a line break and a page break at a particular % place. If the new page is shorter than the old one, the sequence: % \csdisplay % \vadjust{\vfill\eject}\break % | % ^^|\vadjust| % should do the trick. % But if the new page is longer, % the problem is far more difficult because \TeX\ has probably already % squeezed the page as tightly as it can. Your only hopes in this case are % to set ^|\looseness| \ctsref\looseness{} to a negative value, % to shorten some of the vertical skips on the page, to add some shrink to % ^|\parskip| (\xref\parskip) if it was nonzero, or, as a last resort, % to decrease |\baselineskip| \ctsref{\baselineskip} ever so slightly. % ^^|\baselineskip//and preserving end of page| 如果原来的页尾就是正好是两个段落中间,你可以用前面描述的方法在同样位置 强制分页。其他情况下,你必须要在指定位置\emph{同时}强制断行和分页。如 果新页面比旧页面要短,命令序列: \csdisplay \vadjust{\vfill\eject}\break | ^^|\vadjust| 是一个捷径。但是,如果新的页面要长一些的话,问题就非常难办,因为 \TeX{} 可能已经尽量使页面非常紧凑了。这时唯一的办法就是设定 ^|\looseness|\ctsref\looseness{}为负值,来缩短页面上的一些竖直间距, 如果 ^|\parskip| (\xref\parskip) 非零,压缩一下, 或者祭出压箱底的绝 招:略微减小 |\baselineskip| \ctsref{\baselineskip}。 ^^|\baselineskip//用于保留页尾| % \section Leaving space at the top of a page \section 保留页首空白 % \null % ^^{vertical space//reserving at top of page} % You can usually use the |\vskip| command \ctsref\vskip{} % to leave vertical space on a page. % That doesn't work at the top of a page, however, since % \TeX\ discards glue, kerns, and penalties that occur just after a page break. % ^^{page breaks//glue at} % Use the ^|\topglue| command \ctsref\topglue\ instead; it produces glue that % never disappears. % \eix^^{page breaks//bad} \null ^^{竖直间隔//保留页首空白} 通常你可以使用 |\vskip| 命令\ctsref\vskip{} 在页面上添加空白竖直间距, 但这一招对页首无效,因为在紧接着分页后的所有粘连,紧排和惩罚, 都会被 \TeX{} 会丢弃。 ^^{分页//分页处的粘连} 一个替代:^|\topglue| 命令 \ctsref\topglue\ ,能产生永不消失的粘连。 \eix^^{分页//不良分页} % \section Correcting bad line breaks \section 纠正不良断行 % \null % \bix^^{line breaks//bad} % If \TeX\ breaks a line in the middle of material that you wanted to keep % on a single line, there are several ways to correct the situation: % \ulist\compact % \li You can force a break in a nearby place with the % |\break| command (\xref{hbreak}). % ^^|\break//correcting line breaks with| % \li You can insert a tie (|~|) between two words % (see \xref{@not}) to prevent a break between them.\ttidxref{~} % \li You can tell \TeX\ about hyphenations that it wouldn't % otherwise consider by % inserting one or more discretionary hyphens in various words % (see |\-|, \xref{\@minus}). % \ctsidxref{-//in line breaking} % ^^{discretionary hyphens//bad line breaks, correcting with} % \li You can enclose several words in an hbox using the ^|\hbox| % command \ctsref{\hbox}. % \endulist \null \bix^^{断行//不良断行} 如果 \TeX{} 在需要放在一行的内容中间断行了,有好几种方法能纠正这种情况: \ulist\compact \li 你可以使用 |\break| 命令(\xref{hbreak}),在旁边强制断行。 ^^|\break//纠正断行| \li 你可以在两个单词之间插入一个带子(|~|)(见\xref{@not}),来防止在它们之间断开。\ttidxref{~} \li 你可以在一些单词里插入一个或者多个自定连字符,来告诉 \TeX{} 新的断词规则(参考 |\-|,\xref{\@minus})。 \ifoldeplain\ctsidxref{-//在断行中}\fi ^^{自定连字符//纠正不良断行} \li 你可以使用 ^|\hbox| 命令\ctsref{\hbox},把几个单词封装在一个水平盒子里。 \endulist % The disadvantage of all of these methods, except for inserting discretionary % hyphens, is that they may make it impossible for \TeX\ to find a % satisfactory set of line breaks. Should that happen, \TeX\ will % set one or more underfull or overfull boxes and complain about it. % ^^{underfull boxes} ^^{overfull boxes} % The hbox method has a further disadvantage: because \TeX\ sets an hbox % as a single unit without considering its context, the interword space % within the hbox may not be consistent with the interword space in the rest of % the line. % \eix^^{line breaks//bad} 除了插入临时连字符以外, 其他几种方法都有这样的缺点:\TeX{} 不能产生最佳的断行设置。 一旦如此,\TeX{} 将产生一个或多个未满或溢出盒子,并且对此抱怨。 ^^{未满盒子} ^^{过满盒子} 水平盒子的方法还有另外一个缺点: 因为 \TeX{} 处理一个水平盒子的方式是不考虑其中的内容而置其为一个基本单位, 结果盒子内部的单词间距可能会与一行内其它地方不一致。 \eix^^{断行//不良断行} % \section Correcting overfull or underfull boxes \section 纠正溢出或未满盒子 % \null % \bix^^{overfull boxes} % \bix^^{underfull boxes} % \bix^^{boxes//overfull} % \bix^^{boxes//underfull} % If \TeX\ complains about an overfull box, it means you've put % more material into a box than that box has room for. % Similarly, if \TeX\ complains about an underfull box, it means you % haven't put enough material into the box. You can encounter % these complaints under many different circumstances, so let's look at the more % common ones: \null \bix^^{过满盒子} \bix^^{未满盒子} \bix^^{盒子//过满盒子} \bix^^{盒子//未满盒子} 如果 \TeX{} 抱怨一个溢出盒子,那表示你在一个盒子里放置了超出盒子空间的内容。类似的,如果 \TeX{} 抱怨的是一个未满盒子,那是说你没有往盒子里加入足够多的内容。这些抱怨可以在许多情形下发生,所以,让我们先看看一般的情况: % \ulist % \li An overfull hbox that's a line of a paragraph indicates that the line was % too long and that % \TeX\ couldn't rearrange the paragraph % to make the line shorter. If you set ^|\emergencystretch| % \ctsref{\emergencystretch} to some nonzero % value, that may cure the problem by allowing \TeX\ to put more space between % words. Another solution is to set |\tolerance| \ctsref{\tolerance} % to $10000$, but that's likely % to yield lines with far too much space in them. Yet another solution is to % insert a discretionary hyphen % ^^{discretionary hyphens//overfull boxes, correcting with} % in a critical word that \TeX\ didn't know how to hyphenate. % If all else fails, you might try rewording the paragraph. % A solution that is rarely satisfactory is increasing ^|\hfuzz| \ctsref\hfuzz, % allowing \TeX\ to construct lines that project beyond the right margin. \ulist \li 一个水平溢出盒子,如果是段落中的一行,表示那一行太长而且 \TeX{} 不能重新安排段落来缩短它。 如果你设置 ^|\emergencystretch|\ctsref{\emergencystretch} 的值非零, \TeX{} 将在单词间插入更多的空白,可能会有助于解决这个问题。 另一个办法是设置 |\tolerance| \ctsref{\tolerance} $10000$,但它往往会导致行内太多的空白。 还有一个办法是对在 \TeX\ 里未定义断词规则的关键单词插入自定连字符。 ^^{自定连字符//纠正过满盒子} 如果这些都不管用,那你可能只好去重写那个段落了。 一个不是很好的方法是增加 ^|\hfuzz|\ctsref\hfuzz ,来允许 \TeX{} 排版超出右边界的行。 % \li An underfull hbox that's a line of a paragraph indicates that the line was % too short and that \TeX\ couldn't rearrange the paragraph to % make the line longer. % \TeX\ will set such a line by stretching its interword spaces % beyond their normal % limits. Two of the cures for overfull lines mentioned above % also apply to underfull lines: % inserting discretionary hyphens and rewording the paragraph. % Underfull lines % won't trouble you if you're using ragged right formatting, which you can get % with the ^|\raggedright| command \ctsref\raggedright. \li 一个水平未满盒子,如果是段落里的一行,表示那一行太短了,\TeX{} 不能重新安排段落来使之变长。\TeX{} 将加大单词间的空白,甚至超过正常限度。上面提到的对付溢出行的两种纠正办法:插入临时的连字符和重写段落,都可以用于未满的行。对于使用 ^|\raggedright| 命令 \ctsref\raggedright 得到的左对齐格式,就没有未满行的问题。 % \li The complaint: % \csdisplay % Underfull \vbox (badness 10000) has occurred % while \output is active % | % indicates that \TeX\ didn't have enough material to fill up a page. The % likely cause is that you've been using vboxes to keep material together % and \TeX\ has encountered a vbox near the bottom of a page that wouldn't fit on % that page. % It has put the vbox on the next page, but in doing so has left too much % empty space in the current page. % In this case you'll either have to insert some more space % elsewhere on the current page or break up the vbox into smaller parts. \li 抱怨信息: \csdisplay Underfull \vbox (badness 10000) has occurred while \output is active | 表明 \TeX{} 因为没有足够的素材而没有填满一页。可能的原因是: 你使用了竖直盒子来把素材放在一起,但是在接近页面的底部时, \TeX{} 遇到了一个不适合放在那里的竖直盒子。 结果那个盒子被移至下一页,而在当前页上留下了太多空白。 在这种情况下,或者你要在别的地方插入更多的空白, 或者将那个竖直盒子打破,变得小一点。 % Another possible cause of this complaint is having a long paragraph % that occupies an entire page without a break. % Since \TeX\ won't ordinarily vary the spacing between lines, % it may be unable to fill a gap at the bottom of the page % amounting to a fraction of the line spacing. % This can happen if |\vsize| \ctsref{\vsize}, the page length, % is not an even multiple of |\baselineskip| \ctsref{\baselineskip}, % the space between consecutive % baselines. 出现这一抱怨信息的另一个可能原因是:一个长段落覆盖了整页而没有分段。 通常 \TeX\ 不会自动调整基行距离,因此,在一页的末尾,就没法填满不足一个行间距的空白。 如果页面长度 |\vsize|\ctsref{\vsize}恰好不是基线距离 |\baselineskip|\ctsref{\baselineskip}的整数倍,这种情况就会出现。 % Yet another cause of this complaint, % similar to the previous one, is setting ^|\parskip| \ctsref{\parskip}, % the interparagraph glue, to a value that doesn't have any % stretch or shrink. You can fix these last two problems by increasing ^|\vfuzz| % \ctsref\vfuzz. 关于这一抱怨信息还有一个原因:与上面相仿, 段落间的粘连 ^|\parskip|\ctsref{\parskip},被固定为不能拉伸或挤压的值。 后面的这两种情况,你可以增加 ^|\vfuzz|\ctsref\vfuzz 予以解决。 % \li The complaint % \csdisplay % Overfull \vbox (296.30745pt too high) has occurred % while \output is active % | % indicates that you constructed a vbox that was longer than the page. You'll % just have to make it shorter. \li 抱怨信息: \csdisplay Overfull \vbox (296.30745pt too high) has occurred while \output is active | 说的是你构造了一个长于一页的竖直盒子。弄短一点吧。 % \li % \bix^^|\hbox//overfull box from| % \bix^^|\vbox//overfull box from| % The only cures for an overfull hbox or vbox that you've constructed % with the |\hbox| or |\vbox| commands % (\pp\xrefn\hbox, \xrefn\vbox) % are to take something out of the box, to insert some negative glue % with ^|\hss| or ^|\vss| (\xref\hss), or to increase the size % of the box. \li \bix^^|\hbox//它导致的过满盒子| \bix^^|\vbox//它导致的过满盒子| 对于 |\hbox| 或 |\vbox| 命令(第\xrefn\hbox ,\xrefn\vbox 页)所产生的 溢出盒子问题,矫正的诀窍是:从盒子里拿一些东西出去;用 ^|\hss| 或 ^|\vss|(\xref\hss ) 插入负值的粘连;或者增加盒子的尺寸。 % \li If you encounter an underfull hbox or vbox that you've constructed % with |\hbox| or |\vbox|, % you're usually best off to fill out the box with ^|\hfil| % or ^|\vfil| (\xref\hfil). % \eix^^|\hbox//overfull box from| % \eix^^|\vbox//overfull box from| \li 对于 |\hbox| 或 |\vbox| 命令(第\xrefn\hbox ,\xrefn\vbox 页)所产生的 未满盒子问题,只需用 ^|\hfil| 或 ^|\vfil|(\xref\hfil )来填满即可。 \eix^^|\hbox//它导致的过满盒子| \eix^^|\vbox//它导致的过满盒子| % \endulist % \eix^^{boxes//overfull} % \eix^^{boxes//underfull} % \eix^^{overfull boxes} % \eix^^{underfull boxes} \endulist \eix^^{盒子//过满盒子} \eix^^{盒子//未满盒子} \eix^^{过满盒子} \eix^^{未满盒子} % \section Recovering lost interword spaces \section 恢复丢失的单词间距 % \null % ^^{space//lost} % ^^{words run together} % If you find that \TeX\ has run two words together, the likely cause is a % control sequence that's absorbed the spaces after it. % Put a ^{control space} (|\!visiblespace|) after the control % sequence. \null ^^{间隔//丢失的间隔} ^^{单词连在一起} 如果你发现 \TeX{} 把两个单词连在一起,可能的原因是有一个控制序列吃掉 了其后所有的空格。在那个控制序列后面放一个^{控制空格} (|\!visiblespace|) 即可。 % \section Avoiding unwanted interword spaces \section 避免多余的单词间空白 % \null % \bix^^{space//unwanted}\xrdef{unwantedspace} % If you get a space in your document where you don't want and don't % expect one, the most likely cause, in our experience, % is an end of line or a space following a brace. % ^^{braces//space after} % (If you're doing fancy things with category codes, % ^^{category codes//cause of unwanted spaces} % you've introduced lots of other likely causes.) % \TeX\ ordinarily translates an end-of-line into a space, % and it considers a space after a right or left brace to be significant. \null \bix^^{间隔//不想要的间隔}\xrdef{unwantedspace} 如果在文档中有不想要或者未预料到的空白,以我们的经验,最可能的原因是一 行的结尾或大括号后的空格。% ^^{花括号//花括号后的空格}% (当你用类别码来做华丽的效果时, ^^{类别码//导致不想要的间隔} 还会有其他许多类似的原因。) \TeX{} 通常将行尾处理为空格,并且会排出左右大括号后面的空格。 % If the unwanted space is caused by a space after a brace within % an input line, then remove that space. % If the unwanted space is caused by a brace at the end of an input line, % put a `|%|' immediately after the brace. % {\recat!ttidxref[%//to eliminate unwanted spaces]] % The `|%|' starts a comment, but this comment needn't % have any text. 如果多余的空白是在一行内,由大括号后的空格引起的,那就移除它。如果多余的空 白是在行尾,由大括号后的空格引起的,那就紧接着在大括号后放一个`|%|'。 %{\recat!ttidxref[%//to eliminate unwanted spaces]] `|%|' 用于注释开始,但不一定真的要有注释内容。 % A macro definition can also % introduce unwanted spaces if you haven't written it % carefully. If you're getting unwanted spaces when you call a macro, check % its definition to be sure that you don't have an unintended space after a % brace and that you haven't ended a line of the definition immediately % after a brace. % People often end lines of macro definitions after braces in order to make % the definitions more readable. % To be safe, put a `|%|' after any brace that ends a line of a macro % definition. % It may not be needed, but it won't do any harm.\footnote{ % Admittedly there are rare cases where you really do want an end of line % after a brace.} 宏定义如果写的不仔细,也可能导致多余的空白。当你应用一个宏,但是有多余 的空白,那就要检查其定义,确保大括号后没有额外的空格以及紧接着括号之后, 宏定义没有换行。人们经常在大括号后对宏定义换行,从而容易阅读。安全起见, 应该在所有大括号之后要换行的地方放一个`|%|'。可能有些地方不需要,但是这 么做起码没有坏处。\footnote{当然,极为偶然的情况下,你可能真的需要在大括 号后直接换行。} % When you're having trouble locating the source of an unwanted space, % try setting |\tracingcommands| \ctsref{\tracingcommands} to $2$. % You'll get a |{blank space}| command in the log file for each space % that \TeX\ sees. 当你不能准确在源文档中定位多余的空白的时候,可以尝试设置 |\tracingcommands|\ctsref{\tracingcommands}为 $2$。在日志文件里,每 一处空格都会输出一个 |{blank space}| 命令。 % It helps to know \TeX's rules for spaces: 知道 \TeX{} 关于空格的规则会有帮助。 % \olist % \li Spaces are ignored at the beginnings of input lines. % \li Spaces at the ends of input lines are ignored under \emph{all} % circumstances, although the end of line itself is treated like a space. % (A completely blank line, however, generates a |\par| token.) % \li Multiple spaces are treated like a single space, but % only if they appear together in your input. % Thus a space following the arguments of a macro call is not combined % with a final space produced by the macro call. Instead, you get two spaces. % \li Spaces are ignored after control words. % \li Spaces are in effect ignored after numbers, dimensions, % and the `|plus|' and `|minus|' in glue specifications.% % \footnote{Actually, \TeX\ ignores only a % single space in these places. % Since multiple spaces ordinarily reduce to a single space, however, the % effect is that of ignoring any number of spaces.} % \endolist % \noindent If you've changed the category code of the space or the end-of-line % character, all bets are off. % \eix^^{space//unwanted} \olist \li 输入行开始之前的空格将被忽略。 \li 输入行结束之后的空格在任何情况下都被忽略。虽然行尾本身就被当作空格。 (一个空白行产生的是 |\par| 标记) \li 多于一个的空格,如果在一起,将被处理为一个空格。因此,引用一个宏之 后的空格将不会和宏定义末尾的空格合并。你得到的是两个空格。 \li 控制字符之后的空格将被忽略。 \li 数字,尺寸以及粘连设定中的 `|plus|' 和 `|minus|' 之后的空格在执行 中也被忽略。% \footnote{实际上,\TeX{} 在这些地方只会忽略单个的空格。因为多个空格会 被处理为一个空格,所以结果就是忽略所有空格。} \endolist %\section Avoiding excess space around a display \section 避免陈列公式周围的额外空白 % \null % ^^{math display} % If you're getting too much space above a math display, it may be because % you've left a blank line in your input above the display. % The blank line starts a new paragraph and puts \TeX\ into % vertical mode. When % \TeX\ sees a '|$|' in vertical mode, it switches back to horizontal mode % and inserts the interparagraph glue (|\parskip|) followed by % the interline glue (|\baselineskip|). % Then, when it starts the display itself, % it inserts \emph{more} glue (either ^|\abovedisplayskip| % or ^|\abovedisplayshortskip|, depending on the length of the preceding % line). % This last glue is the only glue that you want. % To avoid getting the interparagraph glue as well, don't leave a blank line above a % math display or otherwise % end a paragraph (with |\par|, say) just before a math display. \null ^^{陈列公式} 如果在陈列公式之前有太多空白,有可能是因为你输入的时候在陈列公式之前留 了一个空行。这个空行将开始一个新的段落,并且把 \TeX\ 转入竖直模式。当 \TeX\ 在竖直模式里遇到一个 '|$|', 就会切换到水平模式并插入段间粘连 (|\parskip|),接下来又插入一个行间粘连(|\baselineskip|)。然后当显 示开始的时候,它插入\emph{更多}粘连(或者是 ^|\abovedisplayskip| 或者 是 ^|\abovedisplayshortskip|,取决于前一行的长度)。只有最后一个粘连是你想 要的。为了避免也得到段间粘连,在陈列公式之前不要留空行或者结束段落 (比如用 |\par|)。 % Similarly, % if you're getting too much space below a math display, it may be because % you've left a blank line in your input below the display. % Just remove it. 类似的,如果在陈列公式之后有太多的空白,可能是因为在输入时留了一个空行。 去掉它即可。 %\section Avoiding excess space after a paragraph \section 避免段后的额外空白 % If you get too much vertical space after a paragraph that was produced by a % macro, you may be getting the interparagraph glue produced by the macro, % an empty paragraph, and then more interparagraph glue. % You can get rid of the second paragraph skip by inserting: % \csdisplay % \vskip -\parskip % \vskip -\baselineskip % | % just after the macro call. % If you always get this problem with a certain macro, you can put these % lines at the end of the macro definition instead. % You may also be able to cure the problem by never leaving a blank line % after the macro call---if you want a blank line just to make your input % more readable, start it with a `|%|'. 如果使用宏得到的段落之后有太多竖直空白,可能里头包含了宏产生的段间粘 连,一个空段,以及另外一个段间粘连。你可以通过在那个宏之后插入 \csdisplay \vskip -\parskip \vskip -\baselineskip | 来消除第二个段落间距。 %\section Changing the paragraph shape \section 改变段落形状 % \null % \bix^^{paragraphs//shaping} % Several \TeX\ parameters---^|\hangindent|, ^|\leftskip|, etc.---% % affect the way that \TeX\ shapes paragraphs and breaks them into lines. % ^^{line breaking} % These parameters are used indirectly in \plainTeX{} commands such as % ^|\narrower| and ^|\hang|; you can also assign to them directly. % If you've used one of these commands (or changed one of these parameters), % but the command or parameter change % does not seem to be having any effect on a paragraph, % the problem may be that you've ended a group before you've ended the % paragraph. For example: % \csdisplay % {\narrower She very soon came to an open field, with % a wood on the other side of it: it looked much darker % than the last wood, and Alice felt a little timid % about going into it.} % | % This paragraph won't be set narrower because the right brace at the end % terminates the |\narrower| group before \TeX\ has had a chance to % break the paragraph into lines. Instead, put a |\par| before the % right brace; then you'll get the effect you want. % ^^|\par//when changing paragraph shape| % \eix^^{paragraphs//shaping} \null \bix^^{段落//形成段落} 有几个 \TeX\ 的参数——^|\hangindent|, ^|\leftskip|, 等等——% 影响 \TeX\ 塑段和折行的方式。 ^^{断行} \PlainTeX{} 的命令,如 ^|\narrower| 和 ^|\hang|, 会间接的用到这些参 数;你也可以直接对它们赋值。 如果你已经使用了这些命令中的一个(或者改 变了这些参数中的一个),但是看上去对段落没有任何效果,问题可能在于,段 落结束之前你先结束了一个组。例如: \csdisplay {\narrower She very soon came to an open field, with a wood on the other side of it: it looked much darker than the last wood, and Alice felt a little timid about going into it.} | 这个段落不会变窄,因为最后那个右边大括号在 \TeX\ 拆段组行之前就结束了 |\narrower| 的组。作为补救,放一个 |\par| 在右边大括号之前;这样你才能 看到想要的效果。 ^^|\par//在修改段落形状时| \eix^^{段落//形成段落} %\section Putting paragraphs into a box \section 把段落放入盒子 % Suppose you have a few paragraphs of text that you want to put in a % particular place on the page. The obvious way to do it is to enclose % the paragraphs in an hbox of an appropriate size, and then place the hbox % where you want it to be. Alas, the obvious way doesn't work because % \TeX\ won't do line breaking in restricted horizontal mode. % ^^{restricted mode//horizontal} % If you try it, % you'll get a misleading error message that suggests you're % missing the end of a group. % The way around this restriction is to write: % \csdisplay % \vbox{\hsize = ! !dots ! !dots} % | % where \ is the line length that you want for the paragraphs. % This is what you need to do, in particular, when you want to enclose some % paragraphs in a box (a box enclosed in ruled lines, not a \TeX\ box). 假设你有一些文字段落想放到页面的一个特定位置。显而易见的方式是用一个合 适尺寸的水平盒子来封装段落,然后放到想要的位置。哎呀,这个办法不管用, 因为 \TeX\ 不能在受限水平模式下断行。 ^^{受限模式//水平受限模式} 这么做,你将得到一个有些误导的错误消息,声称 you're missing the end of a group。摆脱这个限制的方法是使用: \csdisplay \vbox{\hsize = ! !dots ! !dots} | 其中,\ 是你希望的一行的长度。这么做就可以了,特别是当你想用盒 子(带线框的盒子,不是 \TeX 盒子)封装一些段落的时候。 %\section Drawing lines \section 画线 % \null % \bix^^{rules} % You can use the ^|\hrule| and ^|\vrule| commands (\xref\hrule) % to draw lines, i.e., rules. You'll need to % know (a)~where you can use each command and % (b)~how \TeX\ determines the lengths of rules when % you haven't given the lengths explicitly. \null \bix^^{标线} 你可以使用 ^|\hrule| 和 ^|\vrule| 命令(\xref\hrule )来画线。 所需知道的是 (a)~在什么地方可以用哪个命令, 以及 (b)~\TeX\ 如何在你未明确指出的情况下决定线的长度。 % \ulist % \li You can only use |\hrule| when \TeX\ is in a vertical mode and |\vrule| % when \TeX\ is in a horizontal mode. % This requirement means that % you can't put a horizontal rule into an hbox or a vertical rule % into a vbox. % You can, however, construct a horizontal rule that looks vertical by % specifying all three dimensions and making it tall and skinny. % Similarly, you can construct a vertical rule that looks horizontal % by making it short and fat. \ulist \li \TeX\ 处于竖直模式时,只能用 |\hrule|;\TeX\ 处于水平模式时,只能 用 |\vrule|。所以你不能在水平盒子里使用横线或者在竖直盒子里使用竖线。 然而,通过设定所有三个尺寸(dimension),你可以把横线画的又高又细,使 它看起来像竖线。类似的,你也可以把竖线画的又矮又宽,使它看起来像横线。 % \li A horizontal rule inside a vbox % has the same width as does the vbox if you haven't % given the width of the rule explicitly. % Vertical rules % inside hboxes behave analogously. % If your rules are coming out too long or too short, % check the dimensions of the enclosing box. % \endulist \li 如果你没有明确设定宽度,竖直盒子里的横线就会和盒子一样宽。水平盒子 里的竖线也类似。如果你得到的线太长或太短,请检查外面盒子的尺寸。 \endulist % As an example, suppose we want to produce: % \display{% % \hbox{\vrule % \vbox{\hrule\vskip 3pt % \hbox{\hskip 3pt % \vbox{\hsize .7in\raggedright % \noindent Help! Let me out of here!}% % \hskip 3pt} % \vskip 3pt\hrule}% % \vrule}} % The following input will do it: % \csdisplay % \hbox{\vrule % \vbox{\hrule \vskip 3pt % \hbox{\hskip 3pt % \vbox{\hsize = .7in \raggedright % \noindent Help!! Let me out of here!!}% % \hskip 3pt}% % \vskip 3pt \hrule}% % \vrule} % | % We need to put the text into a vbox in order to get \TeX\ to process it % as a paragraph. % The four levels of boxing are really % necessary---if you doubt it, try to run this example with fewer levels. % \eix^^{rules} 一个例子,假设你想要 \display{% \hbox{\vrule \vbox{\hrule\vskip 3pt \hbox{\hskip 3pt \vbox{\hsize .7in\raggedright \noindent Help! Let me out of here!}% \hskip 3pt} \vskip 3pt\hrule}% \vrule}} The following input will do it: \csdisplay \hbox{\vrule \vbox{\hrule \vskip 3pt \hbox{\hskip 3pt \vbox{\hsize = .7in \raggedright \noindent Help!! Let me out of here!!}% \hskip 3pt}% \vskip 3pt \hrule}% \vrule} | 我们需要把文本放到竖直盒子里来让 \TeX\ 把它当作段落处理。四层盒子是必 要的---如果你有所怀疑,可以尝试在更少的盒子情况下运行这个例子。 \eix^^{标线} %\section Creating multiline headers or footers \section 创建多行的页眉页脚 % \null % \xrdef{bighead} % \bix^^{headers//multiple-line} % \bix^^{footers//multiple-line} % You can use % the ^|\headline| and ^|\footline| commands % (\xref\footline) to produce headers and footers, but they don't work properly % for headers and footers having more than one line. However, you can get % multiline headers and footers by redefining some of the subsidiary % macros in \TeX's output routine. \null \xrdef{bighead} \bix^^{页眉//多行页眉} \bix^^{页脚//多行页脚} 你可以使用 ^|\headline| 和 ^|\footline| 命令(\xref\footline)来创建页 眉和页脚,但是处理多于一行的页眉和页脚,就不大灵光。然而,通过重新定义 \TeX\ 的输出例行程序的一些宏,就可以实现。 % For a multiline header, you need to do three things: % \olist\compact % \li Redefine the ^|\makeheadline| macro that's called from \TeX's % output routine. % \li Increase ^|\voffset| by the amount of vertical space consumed by the % extra lines. % \li Decrease ^|\vsize| by the same amount. % \endolist % \noindent The following example shows how you might do this: % \csdisplay % \advance\voffset by 2\baselineskip % \advance\vsize by -2\baselineskip % \def\makeheadline{\vbox to 0pt{\vss\noindent % Header line 1\hfil Page \folio\break % Header line 2\hfil\break % Header line 3\hfil}% % \vskip\baselineskip} % | % You can usually follow the pattern of this definition quite closely, just % substituting your own header lines and choosing an appropriate multiple % of |\baselineskip| (one less than the number of lines in the % header). 为了得到多行页眉,你需要做三件事: \olist\compact \li 重新定义 ^|\makeheadline| 宏,\TeX\ 的输出例行程序将会用到它。 \li 把额外的行所需的竖直距离加给 ^|\voffset|。 \li 对 ^|\vsize| 减少同样的大小。 \endolist \noindent 下面的例子演示了你可以怎样做: \csdisplay \advance\voffset by 2\baselineskip \advance\vsize by -2\baselineskip \def\makeheadline{\vbox to 0pt{\vss\noindent Header line 1\hfil Page \folio\break Header line 2\hfil\break Header line 3\hfil}% \vskip\baselineskip} | 一般你照着这个定义的样子做就可以了,只需要替换你自己的页眉内容并选一个 合适的倍数给 |\baselineskip| (页眉行数减一)。 % For a multiline footer, the method is similar: % \olist % \li Redefine the ^|\makefootline| macro that's called from \TeX's % output routine. % \li Decrease ^|\vsize| by the amount of vertical space consumed by the % extra lines. % \endolist % \noindent The following example shows how you might do this: % \csdisplay % \advance\vsize by -2\baselineskip % \def\makefootline{% % \lineskip = 24pt % \vbox{\raggedright\noindent % Footer line 1\hfil\break % Footer line 2\hfil\break % Footer line 3\hfil}} % | % Again, you can usually follow the pattern of this definition quite closely. % The value of |\lineskip| determines the amount of space between the % baseline of the last line % of the main text on the page and the baseline of the first line of the footer. % \eix^^{headers//multiple-line} % \eix^^{footers//multiple-line} 对多行页脚的处理也类似: \olist \li 重新定义 ^|\makefootline| 宏,\TeX\ 的输出例行程序将会用到它。 \li 把额外的行所需的竖直距离加给 ^|\voffset|。 \li 从 ^|\vsize| 减去额外的行所需的竖直距离。 \endolist \noindent 下面的例子演示了你可以怎样做: \csdisplay \advance\vsize by -2\baselineskip \def\makefootline{% \lineskip = 24pt \vbox{\raggedright\noindent Footer line 1\hfil\break Footer line 2\hfil\break Footer line 3\hfil}} | 同样,一般你照着这个定义的样子做就可以了。|\lineskip| 的值决定了页面上正文最 后一行与页脚第一行的基行距离。 \eix^^{页眉//多行页眉} \eix^^{页脚//多行页脚} %\section Finding mismatched braces \section 找出匹配错误的花括号 % \bix^^{braces//mismatched} % \xrdef{mismatched} % Most times when your \TeX\ input suffers from mismatched braces, you'll % get a diagnostic from \TeX\ fairly near the place where you actually % made the mistake. % But one of the most frustrating errors you can get from a \TeX\ run, % just before \TeX\ quits, is % the following: % \csdisplay % (\end occurred inside a group at level 1) % | % This indicates that there is an extra left brace % or a missing right brace somewhere % in your document, but it gives you no hint at all % about where the problem might be. So how can you find it? \bix^^{花括号//不匹配的花括号} \xrdef{mismatched} 大多数情况下,如果有花括号匹配错误, \TeX\ 会在你的输入文档里非常接近错误发生的地方给出诊断信息。 但是,\TeX\ 停止之前最令人沮丧的错误之一是 \csdisplay (\end occurred inside a group at level 1) | 这表明在你的文档中有一个额外的左花括号或者缺少一个右花括号, 但是并没有提示可能出现问题的地方。那么,怎么找到它呢? % A debugging trick we've found useful % is to insert the following line or its equivalent % at five or six places equally spaced within the document (and not within % a known group): % \csdisplay % }% a fake ending % | % Let's assume the problem is an extra left brace. % If the extra left brace % is, say, between the third and fourth fake ending, % you'll get error messages from the first three fake endings but not from % the fourth one. The reason is that \TeX\ will ignore the first three % fake endings after complaining about them, % but the fourth fake ending will match % the extra left brace. % Thus you know that the extra left brace % is somewhere between the third and fourth % fake ending. % If the region of the error % is still too large for you to find it, % just remove the original set of fake endings and % repeat the process within that region. % If the problem is a missing right brace rather than an extra left brace, % you should be able to track it down once you've found its mate. 一条有用的调试技巧是, 在文档内部等距离地插入五到六处类似下面的内容(不要放在已知的编组里): \csdisplay }% a fake ending | 假设问题是多了一个左花括号。如果它在第三和第四个伪装结尾(fake ending)之间, 你将从前三个伪装结尾的地方得到出错消息,第四个则不会。 原因是 \TeX\ 将抱怨并忽略前三个伪装结尾,但是第四个正好匹配了那个额外的左花括号。 这样你就知道了那个额外的左花括号在第三和第四个伪装结尾之间某个地方。 如果嫌疑区域仍然太大,就去除已有的伪装结尾,并在嫌疑区域内重复上述步骤。 如果问题是缺少一个右花括号,一旦你发现左边那个,就能确定右边的了。 % This method doesn't work under all circumstances. In particular, it doesn't % work if your document consists of several really large groups. But often % you can find some variation on this method that will lead you to that % elusive brace. 这个方法不是必杀技。特别是,如果文档中有几个很大的组,这个方法就不那么灵了。 然而大多数情况下,你可以适当地变化一下这个方法来找出暗地捣乱的花括号。 % If all else fails, try shortening your input by removing % the last half of the file % (after stashing away the original version first!) or inserting a % |\bye| command in the middle. % If the error persists, you know it's in the first half; if it goes away, % you know it's in the second half. % By repeating this process you'll eventually find the error. % \eix^^{braces//mismatched} 如果其他方法都不管用了, 那就试着删掉文档后半部分(注意备份!)或者在中间插入一个 |\bye| 命令。 如果问题仍然存在,那你就可以确知它在前一半文档中; 如果没有问题了,你也可以确知问题在后一般文档里。 重复这个过程,最终你将会发现错误所在。 \eix^^{花括号//不匹配的花括号} % \section Setting dimensions \section 设置尺寸 % \null % \bix^^{\} % The simplest way to set a dimension is to specify it directly, e.g.: % \csdisplay % \hsize = 6in % | % You can also specify a dimension in terms of other dimensions or as a mixture % of different units, but it's a little more work. There are two ways % to construct a dimension as such a combination: % \olist\compact % \li You can add a dimension to a dimension parameter or to a dimension % register. % For example: % \csdisplay % \hsize = 6in \advance\hsize by 3pc % 6in + 3pc % | % \li You can indicate a dimension as a multiple of a dimension % or glue parameter or register. % In this case, \TeX\ converts glue to a dimension by throwing away % the stretch and shrink. For example: % \csdisplay % \parindent = .15\hsize % \advance\vsize by -2\parskip % | % \endolist % \eix^^{\} \null \bix^^{\} 设置尺寸的最简单办法是直接赋值,比如: \csdisplay \hsize = 6in | 你也可以用其他尺寸来设定或者混用多种长度单位,这要多费一点事。 有两种方法来创建这样的尺寸组合: \olist\compact \li 你可以增加一个尺寸到另一个尺寸参数或寄存器。例如: \csdisplay \hsize = 6in \advance\hsize by 3pc % 6in + 3pc | \li 你可以将一个尺寸取为另一个尺寸(或粘连)参数或寄存器的倍数。 这时候,\TeX\ 将丢掉粘连的伸长量和收缩量把它转换为尺寸。例如: \csdisplay \parindent = .15\hsize \advance\vsize by -2\parskip | \endolist \eix^^{\} %\section Creating composite fonts \section 创建混合字体 % \null % \bix^^{fonts//composite} % It's sometimes useful to create a ``composite font'', % named by a control sequence $\cal F$, in which all the characters % are taken from a font $f_1$ except for a few that are % borrowed from another font $f_2$. % You can then set text in the composite font by using $\cal F$ just as % you'd use any other font identifier. \null \bix^^{字体//混合字体} 有时候新建一种``混合字体''会很有用处。混合字体命名为一个控制序列 $\cal F$, 它的字符基于一种字体 $f_1$,但是有一些来自另一种字体 $f_2$。然后你 可以像调用其他字体一样使用 $\cal F$ 来设定文本使用混合字体。 % You can create such a composite font by defining $\cal F$ as a macro. % In the definition of $\cal F$, you first select font $f_1$ and then % define control sequences that produce the borrowed characters, % set in $f_2$. % For example, suppose that you want to % create a composite font |\britrm| which has all the characters of |cmr10| % except for the dollar sign, for which you want to borrow % the pound sterling symbol % from font |cmti10|. % The pound sterling symbol in |cmti10| happens to be in the same font position % as the dollar sign in |cmr10|. % Here's how to do it: % \csdisplay % \def\britrm{% % \tenrm % \tenrm names the cmr10 font % \def\${{\tenit\char `\$}}% \tenit names the cmti10 font. % } % | % Now whenever you start the font named |\britrm|, % |\$| will produce a pound sterling symbol. 要创建混合字体,你可以定义 $\cal F$ 为一个宏。宏定义中,首先选择字体 $f_1$, 然后定义控制序列来产生从 $f_2$ 借来的字符。举个例子,假如你要创 建一种混合字体 |\britrm|:基于 |cmr10| 但是其中的美元符号借用 |cmti10| 的英镑符号. 英镑符号在 |cmti10| 的位置恰好跟美元符号在 |cmr10| 里的位置一样。 你可以这样做: \csdisplay \def\britrm{% \tenrm % \tenrm names the cmr10 font \def\${{\tenit\char `\$}}% \tenit names the cmti10 font. } | 现在,当你使用 |\britrm| 字体的时候,|\$| 将生成英镑符号。 % You can also get the same effect by changing the category codes % of the characters in question to make those characters active and then % providing a definition for the character. For example: % \csdisplay % \catcode `* = \active % \def*{{\tentt \char `\*}} % | % In this case the asterisk will be taken from the |\tentt| font. % If you then type the input line: % \csdisplay % Debbie was the * of the show. % | % it will be set as: % {\font\tentt=cmtt10% % \catcode `* = \active % \def*{{\tentt \char `\*}}% % \display{Debbie was the * of the show.}} % \noindent % \eix^^{fonts//composite} 另一种方法会有同样的效果:首先改动类别码(category codes)来激活所考 虑的字符,然后定义它们。例如: \csdisplay \catcode `* = \active \def*{{\tentt \char `\*}} | 这个例子里,星号将从 |\tentt| 字体借用。如果接下来输入: \csdisplay Debbie was the * of the show. | 效果将会是 {\font\tentt=cmtt10% \catcode `* = \active \def*{{\tentt \char `\*}}% \display{Debbie was the * of the show.}} \noindent \eix^^{字体//混合字体} %\section Reproducing text verbatim \section 原文呈现 % \null % ^^{verbatim text}\xrdef{verbatim} % Verbatim text is text that is reproduced in a typeset % document just as it appeared in the input. % The most common use of verbatim text is in typesetting % computer input, % including both computer programs and input to \TeX\ itself. % ^^{computer programs, typesetting} % Computer input is not easy to produce verbatim for two reasons: % \olist\compact % \li Some characters (control symbols, escape characters, braces, % etc.) have % special meanings to \TeX. % \li Ends of line and multiple spaces are translated to single spaces. % \endolist % \noindent % In order to produce verbatim text, you have to cancel the special meanings % and disable the translation. This is best done with macros. \null ^^{原文文本}\xrdef{verbatim} 原文是“输入什么样,就是什么样”的文本。比较常见的是排版计算机输入,包 括计算机程序和 \TeX{} 输入。 ^^{计算机程序,排版} 计算机输入不易以原文呈现的原因是: \olist\compact \li 有些字符(控制字符,转义符,花括号等)在 \TeX{} 里有特殊的含义。 \li 行尾和多个空格会被转换为一个空格。 \endolist \noindent 为了呈现原文,你必须取消这些特殊含义和转换。最好的办法是使用宏。 % To cancel the special meanings, you need to change the category codes % of those characters that have special meanings. % ^^{category codes//for verbatim text} % The following macro illustrates how you might do it: % \csdisplay % \chardef \other = 12 % \def\deactivate{% % \catcode`\\ = \other \catcode`\{ = \other % \catcode`\} = \other \catcode`\$ = \other % \catcode`\& = \other \catcode`\# = \other % \catcode`\% = \other \catcode`\~ = \other % \catcode`\^ = \other \catcode`\_ = \other % } % | % But beware! Once you've changed the category codes in this way, you've lost % the ability to use control sequences since there's no longer an escape % character. You need some way of getting back to the normal mode of % operation. We'll explain how to do that in a moment, after considering % the other problem: disabling the translation of spaces and ends of line. 要取消特殊含义,你可以改变那些字符的类别码。 ^^{类别码//用于原文文本} 接下来的宏演示你如何做: \csdisplay \chardef \other = 12 \def\deactivate{% \catcode`\\ = \other \catcode`\{ = \other \catcode`\} = \other \catcode`\$ = \other \catcode`\& = \other \catcode`\# = \other \catcode`\% = \other \catcode`\~ = \other \catcode`\^ = \other \catcode`\_ = \other } | 小心!一旦这样改变了类别码,就不能再使用任何控制序列了,因为现在不 再有转义符了。你需要想法回到正常的操作模式。接下来,介绍完另一个问 题:取消多个空格和行尾的转换以后,我们将予以解释。 % \PlainTeX\ has two commands that together nearly solve the problem: % ^|\obeyspaces| \ctsref{\obeyspaces} and ^|\obeylines| \ctsref{\obeylines}. % The two things that they don't do are to preserve spaces at the start of % a line % and to preserve blank lines. % For that you need stronger measures---which are provided by % the ^|\obeywhitespace| macro that we are about to define. \PlainTeX{} 有两个命令:^|\obeyspaces|\ctsref{\obeyspaces}和 ^|\obeylines|\ctsref{\obeylines}, 几乎已经解决了上述问题, 除了两件 事:保留行首的空格以及保留多个空白行。对此,你需要更强大的方法——使用 我们将要定义的 ^|\obeywhitespace| 宏。 % \TeX\ normally insists on collecting lines into paragraphs. One way to % convince it to take line boundaries literally is to turn individual lines % into paragraphs.\footnote{% % Another way is to turn the end of line character into a |\break| % command and provide infinite glue at the end of each line. % ^^|\break//end of line as| % } % You can do this by redefining the end of line character to produce % the |\par| control sequence. The following three macro definitions % show how: % ^^{whitespace, preserving} % \xrdef{\obeywhitespace} % \csdisplay % \def\makeactive#1{\catcode`#1 = \active \ignorespaces} % {% The group delimits the text over which ^^M is active. % \makeactive\^^M % % \gdef\obeywhitespace{% % % Use \gdef so the definition survives the group. % \makeactive\^^M % % \let^^M = \newline % % \aftergroup\removebox % Kill extra paragraph at end. % \obeyspaces % % }% % } % \def\newline{\par\indent} % \def\removebox{\setbox0=\lastbox} % | % A subtle point about the definition of |\obeywhitespace| is that % |^^M| must be made active both % when |\obeywhitespace| is being \emph{defined} and when % it is being \emph{used}. \TeX{} 总是收集多行文本为段落。为了原文呈现各行,一个办法是把每一行转换 为独立的段落。\footnote{% 另一个办法是把行尾字符变为 |\break| 命令,并且在每一行尾施加无穷大的粘连。 ^^|\break//将行尾字符变为它| } 你可以重新定义行尾字符来产生一个控制序列 |\par|。下面三个宏定义演示了如 何做: ^^{空白,保留} \xrdef{\obeywhitespace} \csdisplay \def\makeactive#1{\catcode`#1 = \active \ignorespaces} {% The group delimits the text over which ^^M is active. \makeactive\^^M % \gdef\obeywhitespace{% % Use \gdef so the definition survives the group. \makeactive\^^M % \let^^M = \newline % \aftergroup\removebox % Kill extra paragraph at end. \obeyspaces % }% } \def\newline{\par\indent} \def\removebox{\setbox0=\lastbox} | 一个要点是:|^^M| 必须被激活, 无论是\emph{定义} |\obeywhitespace| 还是\emph{使用}它的 时候。 % In order to be able to get back to normal operation after verbatim text, % you need to choose a character that % appears rarely if at all in the verbatim text. This character serves as % a temporary escape character. % The vertical bar (|!||) is sometimes a good choice. % With this choice, the macros: % \csdisplay % \def\verbatim{\par\begingroup\deactivate\obeywhitespace % \catcode `\!| = 0 % Make !| the new escape character. % } % \def\endverbatim{\endgroup\endpar} % \def\!|{!|} % | % will do the trick. Within the verbatim text, you can use a double % vertical bar (|!|!||) to denote a single one, and you end the verbatim text % with |!|endverbatim|. 为了在原文文本之后回到正常的操作模式,你需要选定一个原文文本中几乎不用 的字符来作为临时的转义符。竖线(|!||)经常是一个好的选择。为此,需要宏定 义: \csdisplay \def\verbatim{\par\begingroup\deactivate\obeywhitespace \catcode `\!| = 0 % Make !| the new escape character. } \def\endverbatim{\endgroup\endpar} \def\!|{!|} | 在原文文本中,你可以用双竖线(|!|!||)表示单竖线, 并用 |!|endverbatim| 来结束原文部分。 % There are many variations on this technique: % \ulist % \li If a programming language has keywords, you can turn % each keyword into a command that typesets % that keyword in boldface. Each keyword in the input should then be % preceded by the temporary escape character. % \li If you have a character (again, let's assume it's the vertical bar) % that % \emph{never} appears in the verbatim text, you can make it active and % cause it to end the verbatim text. The macro definitions then go like % this: % \csdisplay % {\catcode `\!| = \active % \gdef\verbatim{% % \par\begingroup\deactivate\obeywhitespace % \catcode `!| = \active % \def !|{\endgroup\par}% % }} % | % \endulist 这个技巧可以有很多变化: \ulist \li 如果一种编程语言有关键字,你可以把关键字变为一个命令,来产生粗体的 关键字。这时候每一个关键字前面都要跟一个临时转义符。 \li 如果有一个字符(假设是竖线)在原文文本中从来没有用到,你可以激活它 并且用它结束原文部分。宏定义将类似于: \csdisplay {\catcode `\!| = \active \gdef\verbatim{% \par\begingroup\deactivate\obeywhitespace \catcode `!| = \active \def !|{\endgroup\par}% }} | \endulist % The ideas presented here provide only a simple approach to typesetting % computer programs. % Verbatim reproduction is often not as revealing or easy to read as a version % that uses typographical conventions to reflect the syntax % and even the semantics of the program. % If you'd like to pursue this subject further, we recommend the following book: % \smallskip{\narrower\noindent % Baecker, Ronald M., and Marcus, Aaron, {\sl Human Factors % and Typography for More Readable Programs}. Reading, Mass.: % Addison-Wesley, 1990.\par} 我们在这里只是提供了简单的办法来排版计算机程序。在反映程序的语法和语义 环境方面,原文呈现经常不是一个清楚、易读的印刷习惯。如果你想在这个主题 上走的更远,我们推荐阅读: \smallskip{\narrower\noindent Baecker, Ronald M., and Marcus, Aaron, {\sl Human Factors and Typography for More Readable Programs}. Reading, Mass.: Addison-Wesley, 1990.\par} %\section Using outer macros \section 使用外部宏 % \null % ^^{forbidden control sequence}^^{incomplete conditional} % If \TeX\ complains about a ``forbidden control sequence'', % you've probably used an outer macro in a non-outer context % \seeconcept{outer}. % ^^{macros//outer} % An outer macro is one whose definition is % preceded by ^|\outer|. % An outer macro can't be used in a macro argument, in a macro definition, % in the preamble of an alignment, or in conditional % text, i.e., text that will be expanded only when a conditional test % has a particular outcome. % ^^{alignments//outer control sequence in} % Certain macros have been defined as outer because they aren't % intended to be used in these contexts and such a use is probably an error. % The only ways around this problem are to redefine the % macro or to move its use to an acceptable context. \null ^^{禁止的控制序列}^^{不完整的条件句} 如果 \TeX{} 警告 ``forbidden control sequence'',很有可能你在非外部环境中 使用了外部宏\seeconcept{外部的}。 ^^{宏//外部宏} 一个外部宏的定义总是以 ^|\outer| 开始. 外部宏不能被用于宏参量 (argument)、宏定义、阵列的导言或者条件文本:只有当某个条件检 验有特定的结果是才展开的文本。 ^^{阵列//其中的外部控制序列} 有些宏被以外部的方式定义是因为我们不想在这些环境里使用它们,一旦使用,必 定出错。解决的办法就是重新定义宏或者移动它们到合适的环境里。 % Using an outer macro in an improper context can also cause % \TeX\ to complain about a runaway situation or an incomplete conditional. % The problem can be hard to diagnose because the error message % gives no hint as to what it is. % If you get such an error message, look around for a call on an outer macro. % You may not always know that a particular macro is outer, but the % command `^|\show||\a|' \ctsref{\show} % will show you the definition of |\a| and also tell you % if |\a| is outer. 在不恰当的环境使用外部宏,还会引起 \TeX\ 警告:不受控制(runaway)的情 形或者不完备的条件。因为错误消息提供不了线索,这些问题通常难于诊断。如 果你得到了这样的错误消息,找找看哪里用了外部宏。可能你并不知道那些宏 属于外部的,`^|\show||\a|'\ctsref{\show} 将显示 |\a| 的定义,并告之 |\a| 是否外部宏。 %\section Changing category codes \section 改变类别码 % \null % \bix^^{category codes//changing} % Sometimes it's useful to make local changes to the category code of a % character in some part of your document. For instance, you might be % typesetting a computer program % ^^{computer programs, typesetting} % or something else that uses normally active % characters for special purposes. You'd then want to deactivate those % characters so that \TeX\ will treat them as being like any other character. \null \bix^^{类别码//改变类别码} 有时候需要在文档的部分内容里局部的改变类别码。例如,排版一个计算机程 序 ^^{计算机程序,排版} 或者将激活的字符用于专门目的。你需 要反激活那些字符来使 \TeX{} 可以像其他字符一样使用它们。 % If you make such a local change to the category code of a character, % you may sometimes be dismayed to find that % \TeX\ seems to be paying no attention whatsoever to your change. % Two aspects of \TeX's behavior are likely causes: 如果局部地改变了类别码,你可能会悲哀地发现 \TeX{} 没有理会你的努力。通 常,原因有两个: % \olist % \li \TeX\ determines the category code of an input character % ^^{input characters} % and attaches it to the character when it reads in the character. % Let's say you read in a tilde (|~|) and later % change the category code of tildes, % but make the change % before \TeX's stomach has actually processed that \emph{particular\/} % tilde \seeconcept{\anatomy}. % \TeX\ will still respond to that % tilde using the category code as it was before the change. % This difficulty typically arises % when the tilde is part of an argument to a macro % and the macro itself changes the category code of tilde. \olist \li \TeX{} 决定输入字符^^{输入字符}的类别码,读到字符的 时候就贴上相应的类别码。假设读到波浪符(|~|),但是在 \TeX{} 的胃还 没有实际消化\emph{那个}波浪符之前改变了它的类别码\seeconcept{\anatomy}。 \TeX{} 将会继续认定原来贴上的类别码。这样的问题通常是因为波浪符是一个 宏定义的一部分,而那个宏里改变了波浪符的类别码。 % \li When \TeX\ is matching a call of a macro to the definition of that macro, % it matches not just the characters in the parameter pattern but also their % category codes. % ^^{macros//arguments of} % ^^{macros//parameters of} % If the category code of a pattern character isn't equal to % the category code of the same character in the call, \TeX\ won't consider % the characters as matching. % This effect can produce mysterious results because it % \emph{looks} as though the pattern should match. % For example, if you've defined a macro: % \csdisplay % \def\eurodate#1/#2/#3{#2.#1.#3} % | % then the slash character must have the same category code when you % call |\eurodate| as it had when you defined |\eurodate|. % \endolist % If the problem arises because the troublesome character is an argument to % a macro, then % the usual cure is to redefine the macro as a pair % of macros |\mstart| and |\mfinish|, where % |\mstart| is to be called before the argument text % and |\mfinish| is to be called after it. % |\mstart| then sets up the category codes and |\mfinish| undoes the change, % perhaps just by ending a group. % \eix^^{category codes//changing} \li 当 \TeX{} 匹配一个宏引用和它的定义时,匹配的不仅仅是参数的字符而且包括他们的类别码。 ^^{宏//宏的参量} ^^{宏//宏的参数} 如果定义里字符的类别码与宏引用里的不同,\TeX{} 不会认为字符匹配正确。 这样的效果匪夷所思,因为\emph{看起来}是匹配的。例如,如果你已经定义了宏: \csdisplay \def\eurodate#1/#2/#3{#2.#1.#3} | 然后斜线字符在引用和定义 |\eurodate| 的时候必须有相同的类别码。 \endolist 如果问题是因为嫌疑字符作为宏参量(argument),诊治方法是重新定义宏为一 对宏 |\mstart| 和 |\mfinish|,分别在参量文本的前后应用。 |\mstart| 设定类别码而 |\mfinish| 结束这一编组来取消变动。 \eix^^{类别码//改变类别码} %\section Making macro files more readable \section 使宏文档易读 % \null % \bix^^{macros//making readable} % You can make a file of macros more readable by % setting the category codes of space to $9$ (ignored % character) and ^|\endlinechar| \ctsref{\endlinechar} to $-1$ % at the beginning of the file. % Then you can use spaces and ends of line freely in the % macro definitions without getting % unwanted spaces when you call the macros. % The ignored characters won't generate spaces, but they'll still % act as terminators for control sequences. % If you really do want a space, you can still get it with the ^|\space| % command \ctsref\space. \null \bix^^{宏//使宏易读} 为了使得宏文档易读,你可以在文档开头设定空格的类别码为 $9$(忽略字符),^|\endlinechar| \ctsref{\endlinechar}为 $-1$。然后,你就可以自由地使用空格和断行而不必 担心产生多余的空白。忽略字符不会产生空白,但仍然决定控制序列定义。如果 你真的需要一个空格,可以用 ^|\space| 命令\ctsref\space。 % Of course you'll need to restore the category codes of space and end of line % to their normal values ($10$ and $5$, respectively) at the end of the file. % You can do this either by enclosing the entire file in a group or by % restoring the values explicitly. If you choose to enclose the file in a group, % then you should also set ^|\globaldefs| to $1$ so that % all the macro definitions will be global and thus visible outside of the group. 当然在文档最后,你需要恢复空格和行尾的类别码(分别是 $10$ 和 $5$):可 以把整个文档封装在一个编组里,也可以明确地恢复其正常值。如果使用编组封 装,你还需要设定 ^|\globaldefs| 为 $1$ 以使得整个宏定义是全局的,在编组之 外可见。 % A miniature example of a macro file of this form is: % \csdisplay % \catcode `\ = 9 \endlinechar = -1 % \def \makeblankbox #1 #2 { % \hbox{\lower \dp0 \vbox{\hidehrule {#1} {#2} % \kern -#1 % overlap rules % \hbox to \wd0{\hidevrule {#1} {#2}% % \raise \ht0 \vbox to #1{} % vrule height % \lower \dp0 \vtop to #1{} % vrule depth % \hfil \hidevrule {#2} {#1} } % \kern -#1 \hidehrule {#2} {#1} } } % \def\hidehrule #1 #2 { % \kern -#1 \hrule height#1 depth#2 \kern -#2 } % \def\hidevrule #1 #2 { % \kern -#1 {\dimen0 = #1 \advance \dimen0 by #2 % \vrule width \dimen0 } \kern -#2 } % \catcode `\ = 10 \endlinechar = `\^^M % | % \noindent % Without the changed category codes, % these macros would have to be written much more compactly, using fewer % spaces and more `|%|'s at the ends of lines. % \eix^^{macros//making readable} 下面是这种格式宏文档的一个小例子: \csdisplay \catcode `\ = 9 \endlinechar = -1 \def \makeblankbox #1 #2 { \hbox{\lower \dp0 \vbox{\hidehrule {#1} {#2} \kern -#1 % overlap rules \hbox to \wd0{\hidevrule {#1} {#2}% \raise \ht0 \vbox to #1{} % vrule height \lower \dp0 \vtop to #1{} % vrule depth \hfil \hidevrule {#2} {#1} } \kern -#1 \hidehrule {#2} {#1} } } \def\hidehrule #1 #2 { \kern -#1 \hrule height#1 depth#2 \kern -#2 } \def\hidevrule #1 #2 { \kern -#1 {\dimen0 = #1 \advance \dimen0 by #2 \vrule width \dimen0 } \kern -#2 } \catcode `\ = 10 \endlinechar = `\^^M | \noindent 不改变类别码的话,这些宏需要写的更加紧凑,使用很少的空格和行尾更多的 `|%|'。 \eix^^{宏//使宏易读} \ifoldeplain\else\ifcompletebook\else \vskip4em{\sectionfonts\leftline{本章索引}} \readindexfile{i} \fi\fi %\endchapter\byebye \endchapter\byebye