在Sublime Text 2中从另一个构建系统访问构建系统

5

我正在尝试为Sublime Text 2创建knitr/Sweave的构建系统。我目前的简单(且有效)的构建系统如下:

{
    "cmd": ["bash", "-c", "/usr/bin/R64 CMD Sweave '${file_name}' && pdflatex '${file_base_name}.tex' -interaction=nonstopmode -synctex=1 %S -f -pdf && /Applications/Skim.app/Contents/MacOS/Skim '${file_base_name}.pdf'"], 
    "path": "$PATH:/usr/texbin:/usr/local/bin", 
    "selector": "text.tex.latex.sweave","shell":false,
    "file_regex": "^(...*?):([0-9]+): ([0-9]*)([^\\.]+)"
}

(text.text.latex.sweave 上下文在 Sweave Textmate 包中定义,该包在 Sublime Text 中基本可用)

构建系统接受一个 .Rnw 文件,将其转换为 TeX,然后对其运行 pdflatex。这个构建系统能够工作,但它在打开 Skim 方面有着相当的局限性(它仅仅打开 PDF 文件)。

LaTeXTools Sublime Text 插件则更加稳健,并在高亮修改的行并提供 Skim 的神奇反向搜索的同时打开/刷新 Skim。

我不想重写 LaTeXTools 的构建系统,特别是因为它使用了单独的 Python 脚本来完成大部分的工作(以及 Skim 的魔力)。然而,我非常希望能够使用它来构建从 Sweave 生成的 TeX 文件。

理想情况下,我希望能够嵌套一个构建系统,即将一个 .Rnw 文件转换为 TeX,然后立即运行已经存在的 LaTeXTools 构建系统。伪代码如下:

{
    [CONVERT RNW TO ${file_name}.tex && RUN THE LATEXTOOLS BUILD SYSTEM ON ${file_name}.tex]
}

能否从另一个构建系统内部访问构建系统(或者从bash访问构建系统)?


至少反向搜索部分可能会很困难,这就是RStudio投入大量精力使其正常工作的地方;对于knitr部分,也许可以这样做:"cmd": ["Rscript", "-e", "knitr::knit('${file_name}')"],其余的工作就是你的问题了:如何调用LaTeXTools?我不使用Sublime Text,所以我不知道... - Yihui Xie
是的,我正在尝试摆脱 RStudio(尽管我很喜欢它),因为 Sublime Text 是一个更优秀的编辑器。我已经有了 knitr 的语言定义和构建系统,但它也有同样的问题——如何使用 LaTeXTools 更强大的构建系统来构建编译后的 TeX 文件(无论是从 Sweave 还是 knitr 制作的)? - Andrew
我也很想知道解决方案 :) - Yihui Xie
1
这里是我所有的ST文件:https://github.com/andrewheiss/KnitrSublime - Andrew
2个回答

5
这是对LatexTools插件中两个文件的补丁,以处理Rnw文件,并对Latex插件进行一个补丁,使Rnw文件的行为类似于LaTeX文件。

首先是针对Latex插件的补丁,具体来说是针对LaTeX.tmLanguage文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>fileTypes</key>
    <array>
        <string>tex</string>
        <string>Rnw</string>
    </array>

请看我如何添加一个元素到数组以处理Rnw扩展。

现在来修改makePDF.py的补丁:

寻找这样一行代码:

if self.tex_ext.upper() != ".TEX":
    sublime.error_message("%s is not a TeX source file: cannot compile." % (os.path.basename(view.file_name()),))
    return

将其替换为

if (self.tex_ext.upper() != ".TEX") and (self.tex_ext.upper() != ".RNW"):
    sublime.error_message("%s is not a TeX or Rnw source file: cannot compile." % (os.path.basename(view.file_name()),))
    return

然后寻找类似以下的一行代码:
os.chdir(tex_dir)
CmdThread(self).start()
print threading.active_count()

并将其替换为

os.chdir(tex_dir)
if self.tex_ext.upper() == ".RNW":
    # Run Rscript -e "library(knitr); knit('" + self.file_name + "')"
    os.system("Rscript -e \"library(knitr); knit('"+ self.file_name +"')\"")
    self.file_name = self.tex_base + ".tex"
    self.tex_ext = ".tex"
CmdThread(self).start()
print threading.active_count()

最后一个补丁是针对jumpToPDF.py文件的。
请查找以下一行:
if texExt.upper() != ".TEX":
    sublime.error_message("%s is not a TeX source file: cannot jump." % (os.path.basename(view.fileName()),))
    return

并用以下内容替换

if (texExt.upper() != ".TEX") and (texExt.upper() != ".RNW"):
    sublime.error_message("%s is not a TeX or Rnw source file: cannot jump." % (os.path.basename(view.fileName()),))
    return

祝你好运!


天啊!太完美了!谢谢! - Andrew
您介意我稍微整理一下这个内容(即与我的 knitr 语言定义结合起来),然后将其作为拉取请求提交到 LaTeX 工具存储库中吗? - Andrew
完全不是这样,我还有另一个补充来实现语法高亮和识别。 - Heberto del Rio
是的,我也是。我还没有开始向LaTeX工具发送拉取请求,因为它似乎是一个非常小众的需求,但我已经将其包含在我的软件包中,网址是https://github.com/andrewheiss/KnitrSublime。 - Andrew

1
感谢Herberto对所需更改的详细描述!
我已经按照要求更改了提到的文件。一切都运作得很好!不过有一件事,我不确定它是否必要,但在编辑它们后,我重新编译了这两个Python文件为.pyc文件。
python -m py_compile makePDF.py

这个工作很不错。如果有人在该行遇到“无效语法错误”,该怎么办?
print threading.active_count()

在重新编译时,只需将其替换为以下内容:


print(threading.active_count())

此外,由于LaTeXTools的日志解析器仅显示来自日志文件的错误,我们可能还想查看knitr输出。您可以通过替换以下内容将其存储在单独的日志文件中:
os.system("Rscript -e \"library(knitr); knit('"+ self.file_name +"')\"")

使用:

    knitcmd = "/usr/bin/Rscript -e \"library(knitr); knit('"+ self.file_name +"')\""
    process = subprocess.Popen(knitcmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    #Launch the shell command:
    knit_output, knit_error = process.communicate()
    #store results in a log
    knit_log = open(self.tex_base + "_knitrbuild.log", "w")
    knit_log.write(knit_output)
    knit_log.write(knit_error)
    knit_log.close()

我之前使用一个简单的bash脚本来构建文档(仅适用于Mac):

#!/bin/bash
[ $# -eq 0 ] && { echo "Usage: $0 file.Rnw for knitting"; exit 1; }
rnw="library(knitr);knit("\'"$1.Rnw"\'")"
echo "Rscript executing:" $rnw
tex="$1.tex"
pdf="$1.pdf"
Rscript -e $rnw && pdflatex $tex && pdflatex $tex && open -a Preview $pdf

retval=$?
[ $retval -eq 0 ] && echo "$rnw knitted and $pdf ready"

但能够自定义 LaTeXTools 并直接从 ST2 运行,并且支持 Skim 是非常好的。
你有什么理由不想直接将你所述的更改添加到软件包源代码中吗?(也许只是我的版本太旧了。)

我无法直接将更改放入ST软件包中,因为它们都涉及LaTeXTools软件包,而我无法控制。在实际的ST软件包中,我解释了手动修补的过程(现在适用于ST 2和3)。此外,您可以使用一个名为latexing的新软件包,它具有对knitr和Skim的内置支持。 - Andrew
哦,ST应该自动将文件编译为.pyc - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接