Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access a build system from another build system in Sublime Text 2

I'm attempting to create a build system for knitr/Sweave in Sublime Text 2. My current, simple (and working) build system is as follows:

{
    "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]*)([^\\.]+)"
}

(The text.text.latex.sweave context is defined in the Sweave Textmate bundle, which kind of works in Sublime Text)

The build system takes a .Rnw file, converts it to TeX, and then runs pdflatex on it. This build system works, but it is fairly limited in how it opens Skim (it just opens the PDF—that's all). The LaTeXTools Sublime Text package is far more robust and opens/refreshes Skim while highlighting modified lines and providing Skim's magic reverse search.

I don't want to rewrite the LaTeXTools build system, especially since it does most of the heavy lifting (and Skim magic) with a separate Python script. However, I would really like to be able to use it to build a TeX file generated from Sweave.

Ideally, I'd love to somehow nest a build system—convert an .Rnw file to TeX and then immediately run the LaTeXTools build system that already exists. In pseudocode:

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

Is it possible to access a build system from inside another build system (or alternatively, access a build system from bash)?

like image 416
Andrew Avatar asked Jan 04 '13 06:01

Andrew


2 Answers

This is a patch to two files in the LatexTools plugin in order to deal with Rnw files, and one patch to the Latex plugin in order to make Rnw files to behave like LaTeX files.

First the patch to the Latex plugin, in specific to the file 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>

Observe how I added an element to the array in order to deal with Rnw extensions.

Now the patch to makePDF.py

look for a a line like this

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

and replace it with

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

Then look for a line like

os.chdir(tex_dir)
CmdThread(self).start()
print threading.active_count()

and replace it with

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()

The last patch is to the file jumpToPDF.py

look for a line

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

and replace it with

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

Good luck!

like image 170
Heberto del Rio Avatar answered Sep 23 '22 13:09

Heberto del Rio


Thanks for the detailed description of the required changes Herberto!

I just went ahead and changed the mentioned files. Everything works like a charm! One thing is though, not sure if it is required, but I recompiled both python files to .pyc after editing them.

python -m py_compile makePDF.py

does the job. Should anyone run into an "invalid syntax error" at the line

print threading.active_count()

while recompiling, just replace it with:

print(threading.active_count())

Also, since the log parser of LaTeXTools only displays errors from the log files, we might be interested to see the knitr output as well. You can store it in a separate log file by replacing:

os.system("Rscript -e \"library(knitr); knit('"+ self.file_name +"')\"")

with:

    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()

Before I was using a simple bash script to build the documents (Mac specific):

#!/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"

but being able to customize LaTeXTools and run it directly from ST2 with Skim support is very nice.

Is there any reasons why you wouldn't want to add the changes you outlined directly into your package source? (maybe my it's only my version that's too old.)

like image 20
means-to-meaning Avatar answered Sep 25 '22 13:09

means-to-meaning