\chapter{一字不差} 在这个信息时代,文档出现一些计算机程序源码片段,是很常见的事。这些代码需要以等宽字体原样显示,像是过去的打字机的输出,故而名曰文本抄录(Verbatim text)。为了让代码更为易读,通常需要根据相应语法对其进行着色渲染。有时,还需要在代码中插入一些其他排版元素。 \section{抄录} 抄录有两种形式,一种是位于一行文字之内,用 \type{\type{...}} 排版,另一种是位于段落之间,用 \type{\starttyping ... \stoptyping} 排版。例如 \startsample \startframedtext[width=\textwidth] 用 C 语言写一个程序,让它在屏幕上显示「\type{Hello world!}」,代码如下 \starttyping #include int main(void) { printf("Hello world!\n"); return 0; } \stoptyping \stopframedtext \stopsample \typesample \noindent 结果为 \start \setuptyping[before={\blank[line]},after={\blank[line]}] \getsample \stop 上述示例,不仅演示了抄录命令的基本用法,你应该也学会了如何使用 \type{framedtext} 环境给一些内容添加朴素的边框。 \section{外框} 也许你也想要一个像本文档中有着巨大的淡蓝色方括号的 \type{typing} 环境,但是需要事先对第 \in[metapost] 章中介绍的 \METAPOST\ 语言的基本用法有所了解方可。给 \type{typing} 环境添加朴素的外框很容易做到,而且它也是实现巨大淡蓝色方括号的基础,方法是 \startsample \setuptyping [before={\startframedtext[width=\textwidth]}, after={\stopframedtext}] \starttyping 带外框的 \starttyping ... \stoptyping \stoptyping \stopsample \typesample \start \getsample \stop 在 \type{\setuptyping} 的 \type{before} 和 \type{after} 参数中,也可以根据自己的需求,添加其他排版命令或你自己定义的宏。\CONTEXT\ 很多命令带有 \type{before} 和 \type{after} 参数。 \section{行号} \type{\setuptyping} 的 \type{line} 参数可用于设定代码行号。通过 \type{\setuplinenumbering} 可调整行号样式。以下示例开启代码行号,并将行号到 \type{typing} 环境的距离设为 0.5 em: \startsample \setuplinenumbering[typing][distance=.5em] \setuptyping [numbering=line, before={\startframedtext[width=\textwidth]}, after={\stopframedtext}] \starttyping #include int main(void) { printf("Hello world!\n"); return 0; } \stoptyping \stopsample \typesample \start \getsample \stop \section{着色} \CONTEXT\ 提供了代码语法着色功能,例如对 \TEX\ 代码进行着色, \startsample \starttyping[option=TEX] \starttext Hello \CONTEXT! \stoptext \stoptyping \stopsample \typesample \start \setuplinenumbering[typing][distance=.5em] \setuptyping [numbering=line, before={\startframedtext[width=\textwidth]}, after={\stopframedtext}] \getsample \stop 不幸的是,目前 \CONTEXT\ 仅实现了 \TEX,\METAPOST,Lua,XML 等代码的着色。不过,对于 \CONTEXT\ 尚不支持的语言,\CONTEXT\ 提供了扩展机制,若你对 Lua 语言及其 Lpeg 库有所了解,可自己动手,丰衣足食\cite[code-render]。 \section{逃逸} 即使不懂 Lua 和 Lpeg,倘若你不嫌麻烦,利用 \type{\type} 和 \type{typing} 环境的逃逸(Escape)机制,也能实现代码着色。例如 \starttyping[escape=no,option=TEX] \starttyping[escape=yes] /BTEX\darkgreen \#include/ETEX /BTEX\darkblue int/ETEX main(/BTEX\darkblue void/ETEX) { printf("/BTEX\darkred Hello world!\n/ETEX"); /BTEX\darkblue return/ETEX 0; } \stoptyping \stoptyping \noindent 结果为 \start \setuptyping [before={\startframedtext[width=\textwidth]}, after={\stopframedtext}] \starttyping[escape=yes] /BTEX\darkgreen \#include/ETEX /BTEX\darkblue int/ETEX main(/BTEX\darkblue void/ETEX) { printf("/BTEX\darkred Hello world!\n/ETEX"); /BTEX\darkblue return/ETEX 0; } \stoptyping \stop 我应该一直都没有告诉你,\CONTEXT\ 该如何给文字着色。\CONTEXT\ 预定义了一些标准颜色,可直接使用这些颜色的名字对文字进行着色,例如「\type{{\magenta 紫色}}」,结果为「{\magenta 紫色}」,也可以使用 \type{\color} 命令,例如「\type{\color[lightmagenta]{浅紫色}}」,结果为「\color[lightmagenta]{浅紫色}」。以下代码可用于查看 \CONTEXT\ 预定义颜色, \starttyping[option=TEX] \startTEXpage[offset=4pt] \showcolor[rgb] \stopTEXpage \stoptyping 使用 \type{\definecolor} 可以通过设定红(r)、绿(g)、蓝(b)分量定义颜色。例如 \startsample \definecolor[myred][r=.8,g=.2,b=.2] \framed{\myred 给你点 color see see!} \stopsample \simplesample[option=TEX]{\getsample} \noindent 上述代码中可以让你你顺便又学会了另一种给文字增加外框的方法。 亦可使用 \type{\colored} 直接设定 rgb 颜色对文字着色,以下代码与上例等效: \startsample \framed{\colored[r=.8,g=.2,b=.2]{给你点 color see see!}} \stopsample \typesample[option=TEX] \section{显示空格} \starttyping[escape=no,option=TEX] \starttyping[space=on] H E L L L O \stoptyping \stoptyping \start \setuptyping [before={\startframedtext[width=\textwidth]}, after={\stopframedtext}] \starttyping[space=on] H E L L L O \stoptyping \stop 注意,\CONTEXT\ 中文断行需要 \type{\setscript[hanzi]},但该命令会吞噬汉字之间的空白字符,从而导致一个问题,在 \type{\type} 和 \type{typing} 环境中,汉字之间若存在空白字符,它们不会被输出到排版结果,此时,只有 \type{space=on} 可以救急。 例如,以下 \type{typing} 环境未开启空格显示: \starttyping 本 行 每 个 汉 字 之 后 都 有 空 格, 但 是 你 看 不 见 它, 除 非 space=on ! \stoptyping \noindent 以下 \type{typing} 环境开启了空格显示: \starttyping[space=on] 本 行 每 个 汉 字 之 后 都 有 空 格, 但 是 你 看 不 见 它, 除 非 space=on ! \stoptyping \section{定义} 使用 \type{\definetype} 和 \type{\definetyping} 可定义专用的抄录环境。例如 \starttyping[option=TEX] \starttyping[escape=yes,space=on,option=TEX] Hello /BTEX\darkred\CONTEXT/ETEX! \stoptyping \stoptyping \noindent 倘若每次使用该 \type{typing} 环境,可能会让你觉得繁琐,且增加了输入出错的风险,采用以下方法可予以简化: \starttyping[option=TEX] \definetyping[foo][escape=yes,space=on,option=TEX] \startfoo Hello /BTEX\darkred\CONTEXT/ETEX! \stopfoo \stoptyping \section{小结} 五色使人目盲。即使 \CONTEXT\ 的代码着色功能未能支持你的程序代码,也许并不值得遗憾。也许真正值得遗憾的是,它未能激发你对 Lua 语言和 Lpeg 库的兴趣,而这正是 \CONTEXT\ 的代码着色功能支持的编程语言过少最重要的原因。