Make Latex bundle for TextMate output files to a ‘target’ directory.

I’m using the LaTeX bundle in TextMate to write pdf files.

Its cool, and gives a nice report of whats going on.

However, it has the habit of putting all the generated files into the same directory as your source, TEX file. I would like it to put everything in a sub directory called “target” so I can easily keep these seperate.

Its easy to get the pdflatex command to do this, you simply specify the -output-dir=./target on the options. And happily, the LaTeX bundle allows me to pass custom options.

1) After running CMD-R, there is a button for “preferences” at the bottom of the output window. Click this and in the typesetting box, select pdflatex and then you can put some options. Put in the string above.

Sweet, so now it generates its stuff into the target dir. Except for a file called (synctex.gzip).

However, the viewer (Skim is good as it syncs the doc position), is still looking for the pdf in the source folder .

A bit of delving about can hack this to work.

2) Open the file. This can be found by showing package contents for your, and going into Contents/SharedSupport/Bundles/Latex.tmbundle

This itself is a package, so again show package contents. Support/bin is where the file is.

You are looking for a function called run_viewer in my version its on line 182. change the following line:

fileNoSuffix = getFileNameWithoutExtension(fileName)


fileNoSuffix = 'target/' + getFileNameWithoutExtension(fileName)

Ok so now it should open up ok, but you also want to be able to jump to a point from the tex file. Do this in sync_viewer, in mine its just above, on line 172. the line you need to change is the same.

This opens the viewer ok, but doesnt sync. Here is where our synctex file comes in. Remember its up in the source folder?

What we need to do is MOVE it to the target folder once the build is completed.

3) Write a new function to move the synctex file to the target dir:

def move_synctex_file_to_target(fileName, filePath):
    """Copies the synctex file to the target directory"""
    fileNoSuffix = getFileNameWithoutExtension(fileName)
    sourceFilename = fileNoSuffix + '.synctex.gz' 
    syncfile = shell_quote(filePath + '/' + sourceFilename)
    targetPath = shell_quote(filePath + '/target/')	
    mvCommand = 'mv '+ syncfile + ' ' + targetPath
    print '<p class="info">Moving synctex file to target [%s]...</p>' % (mvCommand)
    runObj = Popen(mvCommand,shell=True,stdout=PIPE,stdin=PIPE,stderr=STDOUT,close_fds=True)
    stat = runObj.wait()
    return stat

Then you can insert this into the part which is doing the build:

   elif texCommand =='latex':
        texCommand = engine + " " + constructEngineOptions(tsDirs,tmPrefs)
        texStatus,isFatal,numErrs,numWarns = run_latex(texCommand,fileName,verbose)
        if engine == 'latex':
            psFile = fileNoSuffix+'.ps'
            os.system('dvips ' + fileNoSuffix+'.dvi' + ' -o ' + psFile)
            os.system('ps2pdf ' + psFile)
        move_synctex_file_to_target(fileName, filePath)
        if tmPrefs['latexAutoView'] and numErrs < 1:
            stat = run_viewer(viewer,fileName,filePath,tmPrefs['latexKeepLogWin'],'pdfsync' in ltxPackages or synctex)		

We already have these two variables, fileName and filePath. This was line 603 in my installation.

QUESTION: is all this worth it ?

Not sure. Also haven't tried bibtex yet.

So bibtex just required me to change it so that when you loop over the aux files you invoke bibtex with "./target" i.e.:

        runObj = Popen('bibtex'+" "+shell_quote("./target/" +bib),shell=True,stdout=PIPE,stdin=PIPE,stderr=STDOUT,close_fds=True)

Then you have to run bibtex and run pdflatex twice to update your references.

The whole thing is uploaded here - so in theory you can just swap yours out.


Sweet Search And Highlight Command

Been doing quite a bit of manipulating LaTeX files on the command line recently, and have a very sweet little command for searching for text in multiple files:

grep -r Hoffman */*.tex | less +/Hoffman

Where “Hoffman” is the search term which can of course be any regular expression.

The “less” command has a very convenient argument “+” which allows you to pass a search term in and will automatically highlight it for you.

The -r in grep recurses directories and */*.tex looks for all tex files. the | pipes the result to less.