Core TeX“你好,世界!”

Core TeX“你好,世界!”

作为一个实验,我希望用核心 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!\byetex

\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 的评论

相关内容