2012-07-20
1. 前言
txt2tags是一个用python编写的结构化文本工具。使用者只需要编写简单的t2t格式化文本,就能通过软件将t2t源文件直接转化为html、latex、sgml等格式,从而达到一次编写多种格式的效果。同时,利用txt2tags强大的PrePost和PostProc宏替换功能,可以实现很多特殊用途,扩展一些txt2tags本身不易实现的功能。
本文介绍了只编写一个t2t文件,再利用txt2tags及其强大的宏替换功能生成html和latex文件,然后自动用xelatex生成相应的pdf书籍以及beamer幻灯片的方法。利用强大的makefile,可以实现一次编辑自动生成,大大减轻劳动量。
2. 建立编辑环境2.1. 安装txt2tags
首先,系统中最起码要安装有python。windows下面直接到网站上下载安装包并安装,然后去txt2tags的网站上下载txt2tags。将下来的压缩包里面的txt2tags.py解压出来放到python的目录下面,之后将txt2tags.py所在目录添加到系统path目录中去就算是安装完成了。将压缩包里面的语法高亮文件放到指定位置可以在编辑t2t文件时高亮显示。
在debian linux下面安装则要简单多了。直接apt-get python txt2tags就行了,会自动安装到/usr/bin中。不过linux系统里面的txt2tags貌似没有扩展名了,所以使用时候不用加上“.py”。
2.2. 安装latex环境
在windows上面,我使用的是ctex精简版,使用中如果有需要的库会自动在网上下载然后解压。
在debian linux中,可以直接apt-get texlive-full。
2.3. 选择文本编辑器
原则上,可以用任何文本编辑器编写txt2tags的t2t文件,然后通过命令行如“txt2tags.py -t tex main.t2t”编译出所需要的格式。不过我一直习惯vim。emacs据说很好用,甚至可以在书写latex时候直接预览。可惜我下载了txt2tags.el后,发现其自带的语法高亮不太好看,又没有耐心自己写一个。以后有机会试一试emacs吧。
使用vim编辑t2t文件的话,要把默认提供的语法文件进行修改,最好是将不同级别的标题颜色进行修改。直接修改syntax目录下的txt2tags.vim就行,里面还是比较简单的。
3. 前期知识准备之入门知识3.1. 基础知识
- t2t文件分为控制域和正文区域。文件前面三行是留给标题、作者和日期的,之后才能写一些控制语句。控制语句写完之后就可以开始写正文了。
- 控制语句的写法:%!target:html等。
- 正文不需要再写标题和目录了。只要从第一段开始写就行。
3.2. 基本txt2tags语法
效果 | 语法 |
---|---|
粗体 | **粗体** |
斜体 | //斜体// |
下划线 | __下划线__ |
引用 |
``引用`` |
标题 | +第一级标题+ |
+ 列表文字 | + 列表文字 |
更详细标记说明请见:http://txt2tags.org/zh/markup-zh.html
3.3. 宏替换简要说明
名称 | 标记符号 | 用途 | 书写举例 |
转换前替换 | PreProt |
用于在转换前对源文件进行宏替换 | %!PrePost:a b |
转换后替换 | PostProc |
用于在转换后对目标文件进行宏替换 | %!PrePost:a b |
需要注意的是:
- 前替换和后替换都是采用python正则表达式进行的,有的编辑器自带的正则表达式与之不同。
- 两个替换都可以用括号扩起来,从而只对某一格式起作用。
小技巧
- 可以使用通用的注释格式编写自己的替换,并对特定的格式进行前替换,然后再用后替换进行修改。
txt2tags本身基本能够满足一般性文档的书写要求,但有时需要在文档中增加一些新的样式如文字大小、文字颜色、文字对齐方式等,这就需要用到PrePost和PostProc功能。另一方面,虽然txt2tags本身就可以直接生成latex文件,但是默认生成的文件存在无法识别中文、表格不能自动换行、目录标题字母化等若干问题。通过强大的宏替换功能,可以把这些问题解决掉。
我常用的输出格式为html和latex,下面对txt2tags的功能扩充都是基于这两种格式。
4.1. 改变文字的颜色
通过%!PostProc功能,可以在html和latex中实现颜色的控制。比如说:红色和蓝色.
设置域代码:
%!PostProc(tex) : \\{\\{color\s(.*?)\s(.*?)\\}\\} {\\color{\1}\2} %!PostProc(html) : {{color\s(.*?)\s(.*?)}} <font color=\1>\2</font>
使用方法: {{color red 变颜色的文字}}
如果为了兼容性,可以添加下面的代码,%!PostProc : {{color\s(.*?)\s(.*?)}} \2
。不过我个人并没有测试过。同时,颜色区域里面的文字应该支持粗体斜体等样式。
4.2. 文字大小的设定
改变文字大小的方法与改变文字的颜色差不多。例如:小号字和大号字。目前可以设置small和big两种字体。
设置域代码:
%!PostProc(html):{{size\s(.*?)\s(.*?)}} <\1>\2</\1> %!PostProc(tex) : \\{\\{size\sbig\s(.*?)\\}\\} {\\Large \1} %!PostProc(tex) : \\{\\{size\ssmall\s(.*?)\\}\\} {\\small \1}
使用方法: {{size big 大小文字}}
为了兼容性,需要在后面加上一个%!PostProc(html):{{size\s(.*?)\s(.*?)}} \2
,不过这个我一样没有测试过。
4.3. 文字左中右对齐
和前面两种一样的结构,需要写上"align left 文字"之类,目前支持left、center、right三种对齐。
设置域代码:
%!PostProc(html) : {{align\s(.*?)\s(.*?)}} <p align="\1">\2</p> %!PostProc(tex) : \\{\\{align\s(.*?)\s(.*?)\\}\\} \\\1line{\2}
使用方法: {{align left 左对齐}}
注意: 在html中,左中右对齐受到css的影响,如果在css中设置过对齐方式的话,上面的设定就不起作用了。
4.4. 图片自动设置宽度
为了避免插入的图片太大,需要对图片宽度进行控制。 设置域代码:
%!PostProc(tex):(\\includegraphics){(\S+)}\\{(\S+)\\} \1[width=\3\\textwidth]{\2}
之后添加图片只需要
[path/m.jpg]
即可,0.7表示图片宽度为文本宽度的0.7倍宽。
//这个只对latex生效,因为html可以直接显示大图片。
4.5. 设置表格中的文字自动换行
txt2tags里面书写的表格不需要任何设置就能够转换成latex的表格样式。可是有一个问题是如果表格中文字太长就不能换行,从而导致表格溢出。所以需要载入额外的宏包:
\usepackage{tabularx}
设置域代码:
%!PostProc(tex):(begin{tabular)} \1x}{\\textwidth} %!PostProc(tex):(end{tabular)} \1x} %!PostProc(tex):\|l |X
然后就能比较随意的书写表格了。
5. 具体编辑过程5.1. 总体思路
为了实现一个t2t主文件就能生成html、pdf书籍、pdf幻灯片三种格式,我采取的总体思路如下:
- 在1个t2t主文件内编辑文件的正文。
- 建立1个单独的style.css,满足html的样式需要。网络上面css的教程很多,随便看看写一个就行了。
- 将生成书籍和幻灯片所需要的宏替换配置文件独立出来成为一个文件,这样书写时候不用过多考虑后期问题了。
- 将生成书籍和幻灯片所需要的tex配置文件独立出来成为一个文件,这样书写时候不用过多考虑后期问题了。
- 采用一种比较好的方法,能够快速方便的生成三种格式文档,同时也能满足不同操作系统的差异性。
- 考虑到不同操作系统的差异性,进行分平台测试。
5.2. 针对latex需要大量额外宏包载入的解决办法
默认情况下,txt2tags可以将t2t结构化文本直接转化成tex文件。虽然txt2tags会根据t2t文件内容自动载入一些宏包,但是由于中文xelatex的需求以及书签的需求等。我们需要把txt2tags自动生成的导言区替换掉,然后载入一个自己写的latex的导言区配置文档。可以通过宏替换完成这个工作。具体来说大致是这样实现的:
%!PostProc(tex):\\usepackage{graphicx} \\include{conf.slide}\n\usepackage{graphicx}
这样,就可以把实际需要的宏包和设置等写在一个conf.slide.tex中,然后由tex生成pdf时候载入就行了。
5.3. 利用txt2tags自动为beamer添加分页信息
beamer是latex的一个宏包。通过这个宏包可以制作出精炼的slide幻灯片(非PPT)。其实制作slide其基本步骤没有什么变化,只不过完成之后需要手动将所有内容分割在不同的页面中,其实也就是将frame的信息加入到tex文件中去,然后再加上每一页的标题而已。
利用txt2tags的宏替换,可以比较完美的按照subsection和section自动进行分页,这个过程不需要人工干预。宏替换的思路是在每个section/subsection后面开始一个新的页面,在页面链接的前面结束一个页面。 设置域代码如下:
%自动在section和subsection后面开启新页面,同时添加标题和副标题 %!PostProc(tex):^(\\hypertarget)({toc[2-9]\d?}{}) \\end{frame}\n\n\n\1\2 %!PostProc(tex):^(\\hypertarget)({toc1\d+}{}) \\end{frame}\n\n\n\1\2 %!PostProc(tex):^(\\section){(.*?)} \1{\2}\n\n\n\\begin{frame}[t,fragile]{\\insertsection}{\\insertsubsection} %!PostProc(tex):^(\\subsection){(.*?)} \1{\2}\n\n\n\\begin{frame}[t,fragile]{\\insertsection}{\\insertsubsection} %!PostProc(tex):^(\\end{document}) \\end{frame}\n\n\n\1 %删除空白frame,无法生效 %!PostProc(tex):^\\begin{frame}[allowframebreaks,t,containsverbatim]{\\insertsection}{\\insertsubsection}\r\n\r\n\\end{frame} \n
这样在书写t2t源文件时候就不用刻意对每一页进行分页了。
5.4. 手动添加分页信息
如果想要手动分页,可以在需要的位置插入开始新页面和结束新页面的标记。注意:要成对插入。经过测试发现先结束上一页再开启新一页即可。
设置域代码如下:
%!PreProc(tex):^%#beginf <-- %!PreProc(tex):^%#endf --> %!PostProc(tex):^\$<\$-+ \\begin{frame}[allowframebreaks,containsverbatim]{\\insertsection}{\\insertsubsection} %!PostProc(tex):^-+\$>\$ \\end{frame}
举例如下:
%#beginf 这是一个页面的文字。 %#endf
todo
本方法有可能会在section后面新增一个空白页面,尝试过用宏替换去掉。但是至今不会多行替换。
5.5. 手动添加暂停信息
beamer可以通过多页pdf来实现一个暂停的效果,我的做法是在t2t源文件中添加一行标记%#pausef,这个标记会被txt2tags宏替换为\pause。
设置域代码如下:
%添加pause暂停命令 %!PreProc(tex):^%#pausef <pausef> %!PostProc(tex):^\$<\$pausef\$>\$ \n\pause\n
举例如下:
AAA %#pausef BBB
5.6. 使用xelatex进行编译
beamer支持pdflatex以及xelatex两种方式,我采用了后者。这样就能采用系统中自带的字体了。
latex里面使用传统意义上的斜体字还是有些难度的。实际上,我自己的latex中正常字体、粗体、斜体三种字体分别使用了宋体、黑体和楷体。而在linux下面则是使用的AR PL UMing CN和AR PL UKai CN和文泉驿正黑。
具体代码如下:
%windows下面: \setmonofont{SimSun} %解决引用环境里面不能显示中文的问题 \setmainfont[BoldFont=SimHei,ItalicFont=KaiTi_GB2312]{SimSun} \setsansfont[BoldFont=SimHei,ItalicFont=KaiTi_GB2312]{SimSun} %linux下面: \setmonofont{文泉驿正黑} %解决引用环境里面不能显示中文的问题 \setmainfont[BoldFont=文泉驿正黑,ItalicFont=AR PL UKai CN]{AR PL UMing CN} \setsansfont[BoldFont=文泉驿正黑,ItalicFont=AR PL UKai CN]{AR PL UMing CN}
5.7. 同时生成书籍pdf文件和幻灯片pdf文件
可以在t2t文件中直接使用%!include:conf这样的语句来载入conf.t2t,但是txt2tags没有提供类似于条件判断的语句(也可能只是我自己不知道吧),所以无法在同一个文件里面选择书籍和幻灯片各自的宏替换语句。那么就需要两个独立的配置文件了。
我的选择是建立conf.print.t2t和conf.slide.t2t两个文件分别负责书籍和幻灯片的宏替换。当然,两个文件中有一些基本内容是一致的。
同样的,为了降低复杂度。我干脆还建立了conf.print.tex和conf.slide.tex两个文件,这两个文件各自负责相应的tex配置。
5.8. 使用makefile组织编译
源文件较少时,可以直接在命令行敲入命令转换成所需要的文件,但是一旦编译复杂度增加,直接敲击命令行的麻烦程度也会急剧上升。为此,需要用makefile来组织文件编译。通过makefile不仅可以相对简单的将t2t源文件编译成所需要的格式,还能利用条件编译快速地在不同的系统平台进行切换。
为了能实现一个源文件随意生成html、普通pdf和beamer幻灯片三种不同格式的文件,我在makefile里面设置了几个相对独立的目标,同时利用一个变量进行系统平台判断,从而实现条件编译。为了方便查看效果,我顺便利用几个伪目标实现了直接在编译环境里面直接打开阅读目标文件。
最终完成的效果是:
- 用:!make h/p/s<CR>实现生成html/pdf书籍/pdf幻灯片。
- 用:!make vh/vp/vs<CR>实现查看生成的html/pdf书籍/pdf幻灯片,如果文件未生成或者文件已经过时,则重新生成后打开。
- 用:!make c<CR>实现清理所有目标文件以及中间文件。
5.9. 其它一些零碎问题
- 不能在beamer里面使用verbatim环境的问题,可以通过在frame的参数里面添加fragile来解决。原来使用过containsverbatim,不过会导致pause失效,后来换成了fragile一样可以编译通过。
- 有时候section太长了一页写不下,beamer在默认情况下会溢出。可以在frame的参数里面添加allowframebreaks来解决。不过beamer用户手册里面建议不要用这个选项,它也会导致pause失效。所以后来我只在目录里面使用本选项,其它分页则没有采用。这样写完之后就要检查文字是否超出了,自己取舍吧。
- 默认情况下beamer的正文是上下居中对齐的,觉得不好看的话可以在frame的参数里面添加t来解决。
- 默认情况下,section和subsection不会显示在beamer正文中,可以通过PostProc自动在begin{frame}后面插入{\insertsection}{\insertsubsection}来解决。
- 默认情况下,beamer的目录页也是没有标题的,可以通过PostProc解决。语句:```%!PostProc(tex):^(\\tableofcontents) \\begin{center}{\\LARGE 目录}\\end{center}\n\n\1 \n
- windows和linux系统各自的makefile文件编码通常分别设置为gbk和utf8,否则会导致一些问题。同时,在makefile、conf.slide.tex和conf.print.tex中都要进行系统的手动切换。
//本文使用vim编辑而成,可以直接转换为pdf和beamer slide。转载请说明原作者frozenyt@gmail.com。