---
title: 灯火阑珊处
date: '2010-12-24'
slug: solutions-in-the-origin
---

我回忆了好半天，还是想不起当初我为什么对LyX留下了一个错误的印象：它生成的LaTeX文档的前四行是无效的。即这样的代码：

```tex
\batchmode
\makeatletter
\def\input@path{\string"path/to/some where/\string"/}
\makeatother
```

当年我并没有仔细研究第三行，但凭感觉，它是用来定义文档中的外部文件的输入路径的，比如`\includegraphics{}`的根路径。这个感觉并没有错，但当年阴差阳错失败了。我发现LyX的文件名弄乱机制（filename mangling）是因为当时想在Sweave中输出动画，因而需要使用animate包和`\animategraphics{}`命令，但是死活由于找不到输入文件而报错，我花了好几天时间，终于发现原来有这么个机制，以及LyX的编译过程（先复制到临时文件夹再编译）。于是我只好想办法把动画文件先复制到临时文件夹再编译，这当然不是个好办法。还有Sweave，我都是用R脚本把需要的文件复制到LyX的临时文件夹下再让LyX编译，比如需要读入的数据和需要引用的图片文件等。这都是为了让LyX不要抱怨找不到文件。

今天在考虑animation包中的`saveLatex()`如何在Sweave中使用，于是再度看了一下LaTeX的animate宏包的文档，看着看着，突然见到其中有个单词“Important”可以闪动，于是好奇它是怎么做到的，自然也就把源文档找出来看；打开源文档，无意看到这么一句：

```tex
\graphicspath{files/}
```

凭直觉，我觉得这是指定图片文件的根路径，即：文档中的图片引用都以`files/`为基准，在这个文件夹下去寻找。抬手Google了一下，没错，是这样。我想，这不就是我很久以来想要的东西么，只要定义了图片的输入路径，就不必发愁在LyX文档目录和临时文件目录下拷来拷去了。试了一下，对图片`\includegraphics{}`的确管用，但由于我用pgfSweave，图片都是用`\input{}`的方式，这招不管用。

恍惚间，想起了本文开头的那几行命令，琢磨着为什么它们不管用呢，难道有bug？再在LyX中输入了几行LaTeX代码试了试，`\includegraphics{}`和`\input{}`都不写绝对路径，只写相对于LyX文档的相对路径，编译，居然成功了！这简直是个灵异事件。

这下R代码中可以`setwd()`到文档目录了，解决了许久以来的一大麻烦——这是跟人说不清道不明的麻烦。缓存也有了（包括R对象的缓存和图片的缓存），代码高亮也有了，这下可以理直气壮说pgfSweave好用了。


-----------------------过了一天的分割线-----------------------


灯火阑珊处之二：路径的问题解决之后本以为天下太平了，结果新的问题来了。如果使用`external = TRUE`来让pgfSweave缓存图片，那么它会将tikz图片转化为PDF图片（以便下次编译的时候直接引用PDF而不必重新生成一遍tikz，这就是图片能够被缓存的原理），而这些tikz文件默认不是UTF-8编码的，而且我也没有办法控制它的编码。研究了半天，只好用R把tikz读进来用`iconv()`手工转一下编码，于是中文的图片文件也可以正确生成了。但由编码问题导致的悲剧还不只是图片，highlight包对R代码高亮的时候如果遇到中文也死翘翘，关于这一点，实在太难找出原因，因为这个过程中同时涉及到pgfSweave包、highlight包和依赖的包——当错误来源有多种可能的时候查错就很可怕了。最初我以为是我的`tidy.source()`函数有问题，改了半天，未果；然后发现把关掉高亮`highlight = FALSE`之后中文文档可以跑pgfSweave，这说明不是`tidy.source()`的问题；经过艰苦卓绝的追逐，终于发现问题来自parser包的`parser()`函数，它里面涉及到代码读写进出文件，这个问题就像我的formatR包一样，在读写文件过程中，文本的编码信息就丢失了，所以需要在读写之前把编码改成自然编码`options(encoding = "native.enc")`。搞了半天，原来是个老问题。给作者提交了一个patch文件，不知下一个版本是否会更新。


--------------------现在的pgfSweave+LyX状态--------------------


说实话，我一直以来并没有理解图片的缓存是怎么回事。这两天鼓起勇气打开那七百多页的pgf手册瞄了两眼，才真的明白了。现在我的自动配置脚本已经做了大幅度更新，就速度而言基本上已经优化到最佳状态，例如设置[默认图形设备为空设备](/en/2010/12/a-special-graphics-device-in-r-the-null-device/)（这样相比起默认的无用的PDF设备要更节约时间）；将tikz字形字典的目录固定到了文档目录下，这样tikz设备也不必每次都去不同的地方查询字形信息；大量减少了文件的复制，编译的时候只有少数几个文件需要在当前目录和临时目录下互拷；等等。现在的LyX/Sweave（中文）文档，终于完全自由了。
