作为一个实验,我希望用核心 TeX 编写一份手稿,排版文本“Hello, world!”,并在没有任何格式的情况下进行编译。
如果我使用 Plain TeX 格式,这个程序将是
Hello, world!
\bye
因此,为了使该程序独立于格式,我从 plain.tex 中复制了所有缺失的定义,并得到以下内容:
\catcode`\{=1
\catcode`\}=2
\catcode`@=11
\mathchardef\@MM=20000
\def\supereject{\par\penalty-\@MM}
\catcode`@=12
\outer\def\bye{\par\vfill\supereject\end}
Hello, world!
\bye
当我用 编译此稿件时tex -ini
,编译成功,并创建了一个 dvi 文件。但是,dvi 是空的。为什么?
答案1
首先,让我们从一个不使用\bye
宏的更简单的纯 TeX 文件开始:
Hello, world!
\end
这在运行时已经可以正常工作tex
(生成一个包含“Hello, world!”的 DVI 文件),并且(因为它\end
是一个 TeX 原语而不是在 中定义的东西plain.tex
)可以运行时tex -ini
不会出现(可见的)错误,但会生成一个“空白”的 DVI 文件。
为了了解发生了什么,我们可能想开启追踪功能\tracingall
如果我们不知道我们想要哪种类型的跟踪。这\tracingall
是在中定义的,并且按照您的方式plain.tex
从中复制相关部分,则得到:plain.tex
\catcode`\{=1%
\catcode`\}=2%
\catcode`@=11%
\chardef\@ne=1
\chardef\tw@=2
\def\loggingall{\tracingcommands\tw@\tracingstats\tw@
\tracingpages\@ne\tracingoutput\@ne\tracinglostchars\@ne
\tracingmacros\tw@\tracingparagraphs\@ne\tracingrestores\@ne
% \showboxbreadth\maxdimen\showboxdepth\maxdimen}
\showboxbreadth100\showboxdepth100}
\def\tracingall{\tracingonline\@ne\loggingall}
\catcode`@=12%
\tracingall
Hello, world!
\end
(我作弊了一点:上面注释掉的行\showboxbreadth\maxdimen\showboxdepth\maxdimen
是原来的;我只是\showboxbreadth100\showboxdepth100
为了避免必须引入\maxdimen
哪些需要\newdimen
哪些需要的定义\alloc@
等等。)无论如何,有了这个,在输出中更容易看到问题:像
{the letter H}
{horizontal mode: the letter H}
Missing character: There is no H in font nullfont!
{the letter e}
Missing character: There is no e in font nullfont!
等等。实际上,即使.tex
文件较小,你也可以获得此输出:
\tracingonline=1
\tracingcommands=2
\tracinglostchars=1
Hello, world!
\end
无论如何,既然您知道问题出在字体上,您可以从中复制相关部分plain.tex
(再次,我用更简单的等效代码替换了(注释掉的)中的几行plain.tex
,以避免复制大量内容):
\catcode`\{=1 % left brace is begin-group character
\catcode`\}=2 % right brace is end-group character
\font\tenrm=cmr10 % roman text
% \def\rm{\fam\z@\tenrm}
\def\rm{\fam0\tenrm}
% \normalbaselines\rm % select roman font
\rm % select roman font
Hello, world!
\end
运行此命令会tex -ini
排版输出中的字符,但会导致一个有趣的问题:生成的 dvi 文件有两页,一页包含“Hello”,另一页包含“world!”
但原始问题已经解决,所以我将留给你来解开这个谜团。:-)
编辑:为了完整性,这里有一个最小.tex
文件,当使用 运行时,它tex -ini
会生成一个相同的.dvi
文件(当然,除了时间戳注释之外,其他都相同),就像使用 运行时生成.tex
的文件一样:Hello, world!\bye
tex
\catcode`\{=1 % left brace is begin-group character
\catcode`\}=2 % right brace is end-group character
\hsize=6.5in
\vsize=8.9in
\parindent=20pt
\topskip=10pt
\parfillskip=0pt plus 1fil
\font\tenrm=cmr10 % roman text
\def\line{\hbox to\hsize}
\countdef\pageno=0 \pageno=1 % first page is number 1
\output{\plainoutput}
\def\plainoutput{\shipout\vbox{\makeheadline\pagebody\makefootline}}
\def\pagebody{\vbox to\vsize{\boxmaxdepth\maxdepth \pagecontents}}
\def\makeheadline{\vbox to0pt{\vskip-22.5pt \line{\vbox to8.5pt{}\hfil}\vss}}
\def\makefootline{\baselineskip24pt\lineskiplimit0pt\line{\hss\tenrm\number\pageno\hss}}
\def\pagecontents{\unvbox255}
\tenrm % select roman font
Hello, world!
\end
每一行(最后两行之前)要么来自plain.tex
一行,要么是一行的简化版本,删除任何一行都会使 DVI 输出不再相同。(当然,为了简化,我删除了很多有用的内容,例如推进\plainoutput
页码的指令,因此当您有多个段落甚至多行时,这将不起作用,更不用说多页了。)
答案2
跳过 TeX,直接编写 PDF,这是一个无需编译器的解决方案。(只是编译了我从中学到的例子)这个博客)。将其粘贴到文本编辑器中并保存为PDF文件。
%PDF-1.1
%¥±ë
1 0 obj
<< /Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<< /Type /Pages
/Kids [3 0 R]
/Count 1
/MediaBox [0 0 100 15]
>>
endobj
3 0 obj
<< /Type /Page
/Parent 2 0 R
/Resources
<< /Font
<< /F1
<< /Type /Font
/Subtype /Type1
/BaseFont /Times-Roman
>>
>>
>>
/Contents 4 0 R
>>
endobj
4 0 obj
<< /Length 55 >>
stream
BT
/F1 18 Tf
0 0 Td
(Hello World) Tj
ET
endstream
endobj
xref
0 5
0000000000 65535 f
0000000018 00000 n
0000000077 00000 n
0000000178 00000 n
0000000457 00000 n
trailer
<< /Root 1 0 R
/Size 5
>>
startxref
565
%%EOF
答案3
这是一个最小核心 TeX 手稿,排版为“Hello, world!”。
\font\myfont=cmr10\myfont
% When the font is unspecified, it defaults to the nullfont,
% in which glyphs have no visual representation.
% Without this line the dvi page will appear empty.
%
\hsize=10cm
% When \hsize is unspecified, it defaults to 0pt,
% which causes TeX to break page at every whitespace.
% Without this line the words will be placed on separate pages.
%
\parfillskip=0pt plus 1fil
% When \parfillskip is unspecified,
% the whitepasce between words will stretch
% to fill up as much line space as possible
% while keeping all words on a single line.
% The total line width is given by \hsize.
% Without this line the two words will be positioned
% at the opposite sides of a line that is 10cm wide.
%
Hello, world!
\end
* 此答案基于cfr的评论,touhami 的评论,ShreevatsaR 的回答, 和Joseph Wright 的评论。