使用dtx文档类编写源码
在学习和工作中,需要编写程序,但是注释过多的话会影响速度,特别是对于科研工作而言
是一个很重要的参考!
对于一个脚本语言而言,其方便的地方是编程快速,但是其运行速度不如c
等编译型语言,但是从整体来看,编写python
之类的程序会更加方便。不写注释虽然可以提高运行速度,但是时间久了可能自己都读不懂程序在干什么及当时设计思路都无法回忆起来,更别谈及程序维护了。为了调和注释与可维护的矛盾,决定借用latex
宏包的编写思路,使用dtx
文件编写源码与说明文档二合一的文件,这样可以生成纯粹的无任何注释的脚本程序,同时也可以生成PDF
格式的详细说明文档,不仅可以记录设计思路,还可以详细说明技术细节。
完成第一个 Python
脚本示例,实现了源码与注释的分离,使用 xetex
编译
timecristal.dtx
将获得 timecristal.py
无注释脚本程序,使用 xelatex
编译
timecristal.dtx
将会获得脚本的说明文档,详细的记录了各段代码的作用。
分别生成说明文档和程序
这种类型的源码借用了skeleton.dtx
文件,下面说明其应用:
1 | % \iffalse meta-comment |
理解这文件的核心在于第 10 行–第 13 行的代码.第 10
行定义了一个临时命令 \nameoflatexe
由于它是临时起作用,
所以可以使用任何你想要的名称都可以. 由于它是临时的, 所以需要将它限定于
\begingroup
和 \endgroup
之间.
但是根据不同的的功能需求在这时作了特定的设置. 命令 \fmtname
包含了当前执行此文件的程序, 如 (pdf/Xe)LaTeX
编译时,
\fmtname
就是 LaTeX2e
, 当使用
TeX
编译时, 它就不是LaTeX2e
获得宏包文件
使用 TeX
编译二合一的 .dtx
文件.
TeX
读入文件,其中第1行 \iffalse
应当于第36行的
\fi
配对,第3行的 \iffalse
和 第9行的
\fi
配对.第12行的 \ifx
和
第13行及第27行的\fi
配对.文件前面包含 %
的行被忽略,第3行和第9行
之间的部分也不会被执行,这样文件就从第10行开始执行,第11行定义了
\nameoflatexe
第11行使用\expandafter
使\ifx
先于
\endgroup
执行.这样就来到了
\ifx
,由于此时编译程序为 TeX
,所以程序就到了
\else
部分,于是 \csname fi\endcsname
执行,则\ifx
执行完毕,再执行 \endgroup
限定住了
\nameoflatexe
的作用范围,实际上此命令也就没有用了.紧接着调入 docstrip.tex
程序,执行分离程序,一直到第24行 \endbatchfile
则程序终止.由于一直到程序运行终止都还没有运行到第27行的
\fi
,所以这不会出现任何错误.
获得说明文件
使用 XeLaTeX
编译二合一的 .dtx
文件.
XeLaTeX
读入文件,其中第1行 \iffalse
应当于第36行的 \fi
配对,第3行的 \iffalse
和
第9行的 \fi
配对.第12行的 \ifx
和
第13行及第27行的\fi
配对.文件前面包含 %
的行被忽略,第3行和第9行
之间的部分也不会被执行,这样文件就从第10行开始执行,第11行定义了
\nameoflatexe
第11行使用\expandafter
使\ifx
先于 \endgroup
执行.这样就来到了
\ifx
,由于此时编译程序为 XeLaTeX
所以
\ifx
判断的结果为真,则 \else
到第13行
\endcsname
将失效所以 \ifx
还没有执行完成,直到第27行的 \fi
,然后再执行
\endgroup
.
所以第10行到第27行之间的部分将不被执行,也就是跨过 docstrip
程序分离宏包的部分.这样程序忽略其间被 %
注释掉的部分.运行到了第30行,一直到第33行使用 \DocInput
重新调入 .dtx
文件, %
将失去注释符的作用,
在调入文件后再恢复注释作用(这是命令\DocInput
的作用)同时由于第1行的
\iffalse
和第36行的 \fi
配对,
所以这一部分将不被执行.则程序运行到第37行,而第37行一直到第50行是说明文档的内容,则一直遇到第50行的
\endinput
则输入 .dtx
文件执行完毕,回到第34行,遇到 \end{document}
则过程结束.我们将获得和宏包对应的说明文档.
同时生成说明文档和程序
这是第二种方式来编写源文件和注释,并且能够完成源码无注释分离。这里借助了l3doc.dtx
文件,其结构为
1 | \iffalse meta-comment |
此文件也是二合一文件,但是实现代码和 ctex.dtx
不同,所以放在此处作为第二种方法.这代码的的解释为:第1行的
\iffalse
和第 32行的 \fi
配对,第3-6行和
第17-21行配对. 在第3行定义了 \nameofplainTeX
为
plain
, 然后对比编译程序的名字是否为 plain
.如果是, 则略去 \else
后到 第6行的 \fi
部分,即不执行 \begingroup
接下来就是调入
l3docstrip.tex
文件,即开始进行宏包和类文件的分离工作.直到第17行,由于文件名
\nameofplainTeX
就是 plain
,则执行
\endbatchfile
则程序结束.反之,如果在第4行的判断为否,则执行第5行的
\begingroup
同时第 17-21行,执行 第20行的
\endgroup
.则介于 \begingroup
和
\endgroup
的部分一直到最后所有的部分都被执行.
ctex.dtx
执行xetex
只生成pkg.sty
或class.cls
文件,执行xelatex
只生成说明文档ctex.pdf
l3doc.dtx
执行tex
只生成l3doc.cls
或其他宏包,执行latex
则l3doc.cls
和l3doc.pdf
参考文献
- (刘海洋,电子工业出版社2013pdf版)
- (胡伟,清华大学出版社2011pdf)
- (中文翻译版,鲜鲜)
- 文件
- 文件
- 源文件
- 文件
- 这几个\iffalse和\fi是什么意思?
- LaTeX文档编程
- 在 LaTeX 中进行文学编程
- 使用 dtx 文档类文学化编程