我正在尝试为普通的 [Xe]TeX 创建一组宏,以便能够创建 Nassi-Shneidermann 图表来生成表格 ( \halign
)。(我会注意到不同案例的倾斜线不同,我们可以忽略这个问题。)
要创建表格,我需要知道最终 NSD 的列数,因此我需要累积命令。但如果我累积命令,我还必须输入我在调用宏时无法知道的信息,即列数。
所以问题是,我如何制作某种容器,它可以积累标记,并且在使用参数扩展时,它会放入正确的最终结果?例如,如果我们忽略这种图表的边界,并且我想在图表中的 if-then-else 结构之前放置一个命令结构,它将\span\omit
在命令的单元格中生成一对,或者使用 5 个案例结构,它将放置 4 个\span\omit
宏对。
我不知道我希望它在最后阶段是什么样的,但对于一个确切的具体例子,我想要这样的东西:
\beginstruct
\command{i:=1}
\strutif i≠5
\then
j:=j-1
\else
SKIP
\strutfi
\endstruct
得到如下结果:
\halign{
&#\vrule&\hfil#\hfil\cr
\noalign{\hrule}
&i:=1\multispan2&\cr
\noalign{\hrule}
&\char`\\\hfill i≠5\hfill/\multispan2&\cr
\noalign{\hrule}
&j:=j-1&&SKIP&\cr
\noalign{\hrule}
}
但如果我只写:
\beginstruct
\command{i:=1}
\endstruct
会产生如下结果:
\halign{
&#\vrule&\hfil#\hfil\cr
\noalign{\hrule}
&i:=1&\cr
\noalign{\hrule}
}
这里的问题是,我需要知道有 2 列(不包括边框),然后才能向其中写入任何数字\multispan
。在我的第一个示例中,\multispan
后面i:=1
有 2 作为参数,但在第二个示例之后不存在。
答案1
TeX 语言中用于水平对齐的原语\halign
具有前导重复属性,可能在这里有用。\halign
将内容(如果前导中没有另行说明)设置为\hbox
es。以下是其使用的几个示例:
\halign{&\ThisColumnGetsRepeated{#}\cr...}
上述以“与”符号 ( &
) 开头的序言重复了列定义 ( \ThisColumnGetsRepeated{#}
,IE,对每一列重复运行针对给定输入调用的宏\ThisColumnGetsRepeated
),因此您可以给它(通过替换上面的点)无限数量的列:
foo& bar& baz& foo& bar& baz& ... \cr
但是,如果你想要对第一列(比如说)进行一些特殊处理,同时仍然重复其他列,该怎么办?无限地稍后再说?还有另一种形式:
\halign{\SomethingDifferentForThisColumn{#}&&\ThisColumnGetsRepeated{#}\cr ...}
之后的列定义&&
重复。
一旦你爱上了的重复功能,你就会欣赏到在最后一列中\halign
关闭其中的粘性的可能性。 Bruno Le Floch 在\tabskip
他对上一个问题的回答。
另一个问题询问如何重复调用序列\omit\span
。恰巧,plain-tex 格式有一个宏,就是这个。\multispan
以\multispan
它应该的列数作为参数\span
,因此\multispan3
跨越三列,而\multispan{13}
跨越十三列。
为了找出要输入的数字\multispan
,您可以通过两次排版表格来计算列数;第一次只计算列数,尽管我敢打赌计算输入会更容易。在这里我做了困难的方法:
\newcount\colcount
\newcount\maxcolcount
\long\def\maxcols#1{
\global\maxcolcount=0
\everycr={\noalign{\global\colcount=1}}
\setbox0=\vbox{\halign{&##\ifnum\colcount>\maxcolcount
\global\maxcolcount=\colcount\fi\global\advance\colcount by 1\cr#1\cr}}
\the\maxcolcount}
\maxcols{&&\cr&&&\cr&&&&&&&\cr}
^输出:8
然后我尝试从我找到的图像中重现 NSD:
\newdimen\boxitspace\boxitspace=0pt
\long\def\boxit#1{\vbox{\hrule\hbox{\vrule\kern\boxitspace\vbox{%
\kern\boxitspace\parindent0pt#1\kern\boxitspace}%
\kern\boxitspace\vrule}\hrule}}
\offinterlineskip
\boxit{\vbox{\halign{\quad\vphantom{$\Big)$}$#$\hfil&&
\vrule\quad\vphantom{$\Big)$}$#$\hfil\quad\cr
a \gets 1 \cr
\multispan3\hrulefill\cr
b \gets 1 \cr
\multispan3\hrulefill\cr
do~while~a < 12 \hidewidth\cr
\omit& \multispan2\hrulefill\cr
\omit& b \gets a*a \cr
\omit& \multispan2\hrulefill\cr
\omit& output~a,b \hidewidth\cr
\omit& \multispan2\hrulefill\cr
\omit& if~b < 100 \cr
\omit& \multispan2\hrulefill\cr
\omit& T & F \cr
\omit& \multispan2\hrulefill\cr
\omit& a\gets a+1 & a\gets a+2 \cr}}}
\bye
它看起来像这样:
但将所有这些放在一个宏中有点超出我现在的可用时间。也许我以后会再回来做这件事。
TeXing 快乐!:-)