Monthly Archive: September 2010

A possibly better way to customize the TextMate LaTeX plugin

In the aftermath my recent adventures with a development version of a TextMate LaTeX bundle, I wound up reinstalling the original LaTeX bundle, but in the process lost my customizations for special citations and idiosyncratic inline linguistic examples.

I could have re-edited the bundle (that’s why I posted the instructions here, after all, so I could remember what I did), but I discovered a better way, looking at the TextMate manual section on language grammars and on the TextMate wiki: create my own language, subclassing the language from the LaTeX bundle, with just my additions. The advantage of this is that if I ever update the LaTeX bundle, the additions will continue to be mixed in.

This is in fact how the LaTeX Beamer language definition works, so there’s a ready-made example to look at. It defines a couple of special beamer-related things (frame and frametitle), and then includes the regular LaTeX language. So, I am doing just that. Note, though, that if I want to include the beamer specials, I need to include the beamer class. Since I don’t see any real harm in doing so all the time, I am extending that class which itself extends LaTeX.

Here’s how to do this: Go to Bundles > Bundle Editor > Edit Languages…, open up the LaTeX bundle and select the LaTeX Beamer language. Hit the duplicate button in the lower left corner to duplicate it. Then hit the add button and add a new bundle, call it something, and then drag the beamer duplicate into it. Name your duplicate something better, and click on it to edit it. Change scopeName to text.tex.latex.custom. You probably want to get rid of the firstLineMatch line as well, and change fileTypes to ( 'tex' );. The idea is that it will pick up any file with the .tex extension, without checking to see if it is a beamer file.

Then, just put in the additions. I left the beamer additions in, since I use those too. I couldn’t get an include line to work with text.tex.latex.beamer, maybe TextMate doesn’t allow nested includes. Even including both the beamer addition and the main LaTeX language didn’t work, in either order. So, I just left the beamer additions in.

For completeness, this is what I ended up with:

{	scopeName = 'text.tex.latex.custom';
	firstLineMatch = '^\documentclass([.*])?{beamer}';
	fileTypes = ( 'tex' );
	foldingStartMarker = '\begin{.*}|%.*(fold)s*$';
	foldingStopMarker = '\end{.*}|%.*(end)s*$';
	patterns = (
		{	name = 'meta.function.mot.latex';
			contentName = 'string.quoted.mot.latex';
			comment = 'Added by Paul Hagstrom';
			begin = '((\)mot)({)';
			end = '}';
			beginCaptures = {
				1 = { name = 'support.function.mot.latex'; };
				2 = { name = 'punctuation.definition.function.latex'; };
				3 = { name = 'punctuation.definition.mot.begin.latex'; };
			};
			endCaptures = { 0 = { name = 'punctuation.definition.mot.end.latex'; }; };
			patterns = ( { include = '$base'; } );
		},
		{	name = 'meta.citation.latex';
			begin = '(?x)
					(
						(\)										# Marker
						(?:foot)?(?:full)?(?:no)?(?:short)?(?:poss)?(?:pg)?		# Function Name
						[cC]ite
						(?:al)?(?:t|p|author|year(?:par)?|title)?[ANP]*
						*?											# Optional Unabreviated
					)
					(?:([)[^]]*(]))?								# Optional
					(?:([)[^]]*(]))?								#   Arguments
					({)											# Opening Bracket
				';
			end = '}';
			captures = {
				1 = { name = 'keyword.control.cite.latex'; };
				2 = { name = 'punctuation.definition.keyword.latex'; };
				3 = { name = 'punctuation.definition.arguments.optional.begin.latex'; };
				4 = { name = 'punctuation.definition.arguments.optional.end.latex'; };
				5 = { name = 'punctuation.definition.arguments.optional.begin.latex'; };
				6 = { name = 'punctuation.definition.arguments.optional.end.latex'; };
				7 = { name = 'punctuation.definition.arguments.latex'; };
			};
			endCaptures = { 0 = { name = 'punctuation.definition.arguments.latex'; }; };
			patterns = (
				{	name = 'constant.other.reference.citation.latex';
					match = '[w:.]+';
				},
			);
		},
		{	name = 'meta.function.environment.frame.latex';
			begin = '(?:s*)((\)begin)({)(frame)(})';
			end = '((\)end)({)(frame)(})';
			captures = {
				1 = { name = 'support.function.be.latex'; };
				2 = { name = 'punctuation.definition.function.latex'; };
				3 = { name = 'punctuation.definition.arguments.begin.latex'; };
				4 = { name = 'variable.parameter.function.latex'; };
				5 = { name = 'punctuation.definition.arguments.end.latex'; };
			};
			patterns = ( { include = '$self'; } );
		},
		{	name = 'meta.function.frametitle.latex';
			match = '((\)frametitle)({)(.*)(})';
			captures = {
				1 = { name = 'support.function.frametitle.latex'; };
				2 = { name = 'punctuation.definition.function.latex'; };
				3 = { name = 'punctuation.definition.arguments.begin.latex'; };
				4 = { name = 'entity.name.function.frame.latex'; };
				5 = { name = 'punctuation.definition.arguments.end.latex'; };
			};
		},
		{	include = 'text.tex.latex'; },
	);
}

Tex Touch: LaTeX on the iPad that doesn’t even hurt much

I just took Tex Touch for a spin on the iPad, and actually did some substantial editing on a paper. It’s not as fast to type on an iPad as it is on a real keyboard, of course, but I’m pretty impressed with how it works.

The fundamental problem with TeX on an iDevice is that Apple forbids any kind of code compilation on the device itself, and so one couldn’t even in principle do a TeX install on the iPad (at least without jailbreaking, I don’t know what options are open for a jailbroken iPad). So, the only way to make it work is to do the compiling remotely. However, TexTouch makes the process pretty transparent.

Tex Touch allows you to connect yourself to a folder in your Dropbox account (and for the space you need, the free account will suffice), and then it will use that folder as a way to connect to your desktop machine, which needs to be running a program that will watch the folder and compile any TeX files that find themselves there. When the compilation is done, and the PDF file is produced, TexTouch picks it up and allows you to display it on the iPad. The folder watching function is accomplished either by the developer’s own program or by using Ramón Figueroa-Centeno’s LaTeXMe script. LaTeXMe is a Mac program, but Tex Touch itself is intended to also work with a Windows machine on the remote compiler end.

Once you have it set up, you barely realize that it’s being compiled remotely. You hit the “TeX!” button and the file is uploaded, it sits for a little bit, then downloads the PDF (or gives you access to the log).

The editor itself is nice too. No syntax coloring yet, but it has support for templates, and it has an elaborate keyboard setup that allows pretty simple access to brackets and slashes and commonly used LaTeX commands and symbols. After working with it briefly, I found it quite acceptable.

I’m looking forward to seeing how it develops, but this looks like the perfect solution for my own setup. I already keep all of my TeX work in my Dropbox folder anyway, so it’s pretty straightforward to copy over a file I want to work on when I’m away from my computer and get still something done. The only problem that I have had so far is that it didn’t find my bibliography file when it was remotely compiling, but I’m sure that (a) this is pretty easily solvable by adding a path to something somewhere, and (b) I’m unlikely to produce the final version of the PDF this way anyway, so I’ll always have a chance to recompile when I get back to my computer.

A nicer LaTeX bundle for TextMate

When a document I was trying to compile kept alerting me to fatal errors, but scouring the log file failed to reveal anything that should count, I decided I’d poke around a little bit to see if there were any updates to the LaTeX bundle for TextMate. I found, first, that it seemed to have actually disappeared from the TextMate svn repository, but, second, that there is a relatively nice version maintained by Adam Strzlecki on github. I haven’t done a great deal of exploration, but it does seem to be a bit faster, and there are a few added niceties to the autocompletion mechanisms.

I updated to the new bundle, but since I had made some changes to the old one (see Adding a little bit to TextMate’s LaTeX bundle and More TextMate LaTeX language editing), I decided to fork the existing repository and add those in as well.

Additionally, at present, the current bundle chokes a little bit on files that are within folders that contain spaces in their names. Compilation still works, but the links to errors that you should get in the status window are broken, as is the “jump to corresponding location in the PDF” command. I’ve fixed both of these problems in my fork of the bundle (though it is possible that there are hidden problems I’ve introduced, particularly in the thing that processes error links, I haven’t tried it with a complex master document).

Update: The sad truth is, this is not ready for prime time yet, at least not for me. I rely heavily on the dvi-ps-pdf pathway, and this bundle seems to have disabled it. I tried for a while to re-enable it, but it just wasn’t cooperating. Maybe in the lazy days of Thanksgiving break, but for now I would recommend against installing this bundle.

To install my fork of the TextMate LaTeX bundle, you need to remove the old one (maybe just put it somewhere safe in case you want to go back to it) from ~/Library/Application Support/TextMate/Bundles/ (maybe also check in /Library), and disable or remove the built-in LaTeX bundle. (I, perhaps unwisely, just pulled it out of the .app: right-click on the TextMate application, show package contents, open Contents, Shared Support, and Bundles, wherein is LaTeX.tmbundle.)

To install the new bundle, you need to have git installed. If you don’t, there is some information at github about installing git on Mac OS X.

That done, open a Terminal window and type thusly:

cd ~/Library/Application Support/TextMate/Bundles/
git clone git://github.com/paulhagstrom/LaTeX.tmbundle.git

The next time you start TextMate, the new bundle should be active.

Now, back to that paper.

Printing handouts from the T

Once again, I arrive at the T stop just to see the train I needed to get to class on time pulling away. I still need to print my handouts, but I am barely going to be able to be physically there by the time the class is scheduled to start.

What to do?

Well, I have 20 minutes on the T, and my handout files are kept in my Dropbox folder, which means that my handout is actually on my office computer’s hard drive. And I have an iPhone on which I have installed iSSH. iSSH is a fabulous app, complete with VNC capability, so I figured: I’ll just put my office computer’s desktop on my phone, open the handout, and print.

Except something is configured wrong, or I’ve forgotten the VNC password, something is preventing me from bringing up my office computer’s screen on my phone. I can, however, still ssh in to the command line on that computer.

So: how to print from the command line?

Although there is rarely call to use it, it is relatively straightforward to send things to the printer, and the CUPS printing system installed as part of Mac OS X is smart enough to know what to do with PDF files, and can send options to the printer like: print double-sided, staple, print 2-up, etc. You just use the lp command. Here is the specific command I used.


lp -d printer_name -n 15 -o Collate=True -o Staple=1PLB -o number-up=2 -o sides=two-sided-long-edge ~/Dropbox/.../handout.pdf

Of course, this won’t work for everyone’s printer setup, one needs to know what the printer’s name is, and what options are available. But these are fairly easy to determine, based on things I learned from this page of the CUPS documentation.

If you need to find out what printers your computer knows about, enter lpstat -p -d at the command line. In the print command I gave above, I pretended that one of the printers was called printer_name, although really it was named after its IP address on the network. The number 15 I put there after the -n option is the number of copies to print. The options indicated with -o are printer-specific options for stapling, printing n-up, etc. You can find what options your printer supports using lpoptions -p printer_name -l.

So, as long as there is paper in the printer, and there are no forthcoming paper jams, it is possible to make the printer do its thing all on its own, so that I can pick them up when I get there and go to class. Fairly nerdy, but pretty cool. And occasionally practical.

Syntax highlighting in WordPress

There doesn’t seem to be anything built in to WordPress that does syntax highlighting, but there are a lot of plugins that can help with this. After looking around a bit, I opted for SyntaxHighlighter Evolved by “Viper007Bond.”

It was an easy install with WP 3.0.1, and it includes support for LaTeX (a third-party addon to the SyntaxHighlighter by Alex Gorbatchev that all of these plugins use). But it didn’t include support for AppleScript, which I do occasionally want to exhibit.

There is an add-on “brush” for AppleScript by David Chambers that can be added, but in order for it not to break whenever SyntaxHighlighter Evolved is updated, it needed to be constructed as its own dependent WordPress plugin. Fortunately, Viper007Bond left instructions on how to do this, and it is pretty straightforward.

What I did is create the following file in the directory syntaxhighlighter-applescript within my WordPress plugins directory, calling the file syntaxhighlighter-applescript.php:

<?php
/*
Plugin Name: SyntaxHighlighter Evolved: AppleScript Brush
Description: Adds support for the AppleScript language to the SyntaxHighlighter Evolved plugin.
Author: Paul Hagstrom
Version: 1.0.0
Author URI: http://ug.bu.edu/blog/lingtech/
*/

// SyntaxHighlighter Evolved doesn't do anything until early in the init hook, so best to wait until after that
add_action( 'init', 'syntaxhighlighter_applescript_regscript' );

// Tell SyntaxHighlighter Evolved about this new language/brush
add_filter( 'syntaxhighlighter_brushes', 'syntaxhighlighter_applescript_addlang' );

// Register the brush file with WordPress
function syntaxhighlighter_applescript_regscript() {
  wp_register_script( 'syntaxhighlighter-brush-applescript', plugins_url( 'shBrushAppleScript.js', __FILE__ ), array('syntaxhighlighter-core'), '1.2.3' );
  wp_enqueue_style(  'syntaxhighlighter-style-applescript', plugins_url('shThemeAppleScript.css', __FILE__), array('syntaxhighlighter-core'), '1.2.3' );
}

// Filter SyntaxHighlighter Evolved's language array
function syntaxhighlighter_applescript_addlang( $brushes ) {
  $brushes['applescript'] = 'applescript';
  return $brushes;
}

?>

I then downloaded the AppleScript brush, AppleScript theme, and background image from David Chambers’ site and put them in the same directory.

Back in WordPress, I activated this new plugin, and then styled the AppleScript (on, for example, this post) using the following markup:

;

Note that it requires the addition of the classname="applescript" part in order to pick up the CSS in the additional stylesheet.

For LaTeX, I ran into a different problem, specifically in connection with pstricks code and jTree (e.g., on this post), because there is sometimes need for code that includes the left and right angled brackets, which were being turned into &lt; and &gt;. To solve that, I had to use the “<script> method” for code embedding, like so:

<script type="syntaxhighlighter" class="brush:latex"><![CDATA[
\jtree
...
\endjtree
]]</script>;

Adding an interleave document option to Acrobat (or, ClearScan bites me again)

I’ve mentioned the joys and the agonies of Acrobat’s ClearScan technology before. It produces wonderful output, small, clear, OCR’ed, but unreliable. Recently, I discovered another way in which it is unreliable, apart from sometimes silently cutting off the ends of lines.

The symptom: I noticed that some of my nicely ClearScanned PDFs, although they appear to have selectable text, were not actually searchable and copying and pasting yielded just a bunch of repeated garbage characters. Not good.

The underlying cause: eventually, I realized what the problem is. It has to do with how ClearScan works. What ClearScan does is go through the scanned image and “smooths” it by creating a (vector!) font that closely approximates the shape of the rasterized object (generally, a letter). So, it creates a new, special, document-specific vector font for each document you OCR, and embeds it in the PDF. However, something important about this font information is lost if you ever modify and save this file in something other than Acrobat (say, in Preview). The result seems to be that all information about the font character-to-letter mapping is lost, and so the recognized text is gone (though the PDF still looks beautiful and small).

How I got bitten by this: The reason I lost my font information has to do with my scanning workflow. Generally, I scan things 2-up on a copier (or scan photocopies that I had previously photocopied 2-up), and so when I get this into Acrobat, I create two further files, one cropped to show just the left side pages, and the other cropped to show just the right side pages. Then I OCR each side independently. Then, I merge them using a simple Automator script that just runs the built-in “Combine PDF pages by shuffling” action, so that I have a single 1-up PDF with the pages in the right order. That’s the fatal step. The “Combine PDF pages by shuffling” command creates a new PDF out of the old ones, using Apple’s own internal PDF kit, and in the process, loses/garbles the font mapping.

The solution, then, is to interleave the OCR’ed left and right page PDFs within Acrobat, which will preserve this information. Except that, stunningly, Acrobat still doesn’t have a command that does this. Really. It’s crazy. Perhaps even more stunningly, though, searching the web really didn’t find much by way of a solution to this, or even complaints about it. What are people using Acrobat for anyway?

What Acrobat does have is a fairly elaborate Javascript interpreter that can do all kinds of PDF manipulations and other things, if you’re enough of a nerd to wade through the process of using it. So, I set myself to the task of creating a small Javascript application that would take two PDFs and make a new PDF from them, alternating the source.

One way this can be done is to copy the following text into a Javascript file (or download it from here), call it something like interleave-tool.js) that you put in your Acrobat startup scripts folder. On my MacBook, this folder is ~/Library/Application Support/Adobe/Acrobat/9.0_x86/Javascripts. (For Acrobat X, the folder is …/10.0/Javascripts instead.) What it does is install a menu item under the edit menu (“Interleave document…”) which will ask you to browse to a PDF file, and then insert the pages from the selected file into the currently frontmost document (where the first inserted page is after the first page of the current document). That’s all I needed. Pretty big headache to do a pretty simple (and commonly needed, I should think!) thing.

// add interleave option to Edit menu
// Paul Hagstrom
// September 2010

// Add a menu item for interleaveDocument
app.addMenuItem( {
   cName: &quot;interleaveDocument&quot;,
   cUser: &quot;Interleave document...&quot;,
   cParent: &quot;Edit&quot;,
   cEnable: &quot;event.rc = (event.target != null);&quot;,
   cExec: &quot;InterleaveDocument(event.target)&quot;
});

// main interleave function
InterleaveDocument = app.trustedFunction(
	function(doc) {
		// escalate privileges
		app.beginPriv();
		// ask for the document to interleave
		var srcFile = app.browseForDoc({});
		// if they didn't cancel
		if ( typeof srcFile != &quot;undefined&quot; ) {
			// open the source document
			var srcDoc = app.openDoc({
				cPath: srcFile.cPath,
				bHidden: true
			});
			// count the pages
			var srcPages = srcDoc.numPages;
			// and close the source doc
			srcDoc.closeDoc();
			// start inserting after the first page
			var insAfterPage = 0;
			// for each page in the source document
			for(var pg = 0; pg &lt; srcPages; pg++) {
				// insert it into the current document
				doc.insertPages({
					nPage: insAfterPage++,
					cPath: srcFile.cPath,
					nStart: pg
				});
				// increment again past just-added page
				insAfterPage++;
			}
		}
		// descalate privileges
		app.endPriv();
	}
);

Incidentally, here’s another ridiculous thing that I discovered while trying to debug this script: you can’t use the Javascript console properly on a MacBook. It doesn’t have the key you need to trigger a script to execute. One workaround that I found by searching the web is to use the keyboard viewer, physically hold down Fn and Ctrl, and use the mouse to click the Enter button on the keyboard viewer. You’ve got to be kidding. An easier way is to use KeyRemap4MacBook, which I am using anyway to get my en-dashes back. I chose to make my right option key into Enter, which is what it should have been in the first place. Turns out, when you do this, just pressing Enter (unmodified) executes the script (despite everything written everywhere suggesting that you need to press Ctrl-Enter).