George MacKerron: code blog

GIS, software development, and other snippets

Tab completion for Stata variables in TextMate

I recently switched to TextMate for editing Stata .do files: unlike Stata’s built-in editor on the Mac, it has syntax highlighting and other goodies via Timothy Beatty’s bundle (now hosted by Dan Byler).

One thing it doesn’t have, though, is tab completion. Or rather, it didn’t, until now.

What does it do?

It’s the same thing you get in Stata’s Command window: you type part of a variable name, press tab, and the name is completed as far as it can be without ambiguity.

For example, I type —

tab fr

— I press tab —

tab fruit_and_veg__q

— and the variable name is completed, leaving the cursor one space to the right and ready to keep typing. (Note that my use of Stata’s tab[le] command in these examples is an unfortunate coincidence and has nothing to do with tab completion! I could just as well have written regress fr. Sorry.)

In fact, proper tab completion (as found in Unixy shells, for file names, but not in Stata’s Command window) goes a little further than this: if you press tab at the end of an ambiguous name stem, it prompts you with all the possible endings.

And so it is with this TextMate bundle addition. I type —

tab pol

— I press tab —

tab politic

— and the name is completed up to the next ambiguity. So I press tab again —

List of suggestions

— and I get a tooltip list of options. I add an ‘s’ (just enough to pick one option out) —

tab politics

— press tab again —

tab politics_left_right__q

— and bingo!

How does it work?

Each time you press tab, the bundle asks Stata to run a simple .do file; this exports your current data set with an if 0 condition, meaning that all the actual data is excluded, and we just get the variable names. (For detail, check the Ruby script).

A slightly unfortunate effect of this is that your Stata Results window (and log, if you’re keeping one) fills up with these outsheet commands. I hope that’s not a deal-breaker. If only Stata would provide some basic AppleScript support (please?) I might be able to do something about this.

How do I get it?

Update! As per comments below, you can now download the bundle with tab completion rolled in, so you can probably stop reading here.

At some point I may roll this into a new bundle file to make installation easier (there are also a few fixes I’ve made to the original bundle). But in the meantime, you can add it to the bundle yourself.

Open the bundle editor (Bundles > Bundle Editor > Show Bundle Editor) and select the Stata bundle. Click the ‘+’ button and select ‘New Command’. Give the command a name. Then, on the right, select Save: Nothing, Input: Selected Text or Word and Output: Replace Selected Text. Choose Activation: Key Equivalent: and a hotkey (I use Ctrl-Tab).

Then paste in the following Ruby script:

#!/usr/bin/env ruby
require ENV['TM_SUPPORT_PATH'] + '/lib/exit_codes.rb'
dofile = '/tmp/'
varfile = '/tmp/textmatestatavars.tsv'
stem = '' if stem.nil? || stem.match(/\s$/)
stem = stem.lstrip
TextMate.exit_discard if stem.match(/[^a-z0-9_]/im)
open(dofile, 'w') do |f| 
  f.print %{set notifyuser off\noutsheet #{stem}* using "#{varfile}" if 0, noquote\n}
File.unlink(varfile) if File.exist?(varfile)
`osascript -e 'tell application "Stata" to open POSIX file "#{dofile}"'`
unless File.exist?(varfile)
  print 'No variables found'	
vars = open(varfile) { |f|"\t") }
if vars.length == 1
  print vars.first + ' '
v1, v2 = vars.sort.values_at(0, -1).sort_by { |v| v.length }
common_prefix = (0...(v1.length)).each do |i|
  break v1[0, i] unless v1[i, 1] == v2[i, 1]
common_prefix = v1 unless common_prefix.is_a?(String)
if stem == common_prefix
  print vars.join("\n")
  print common_prefix

It should look like this:



Written by George

February 6th, 2010 at 5:59 pm

Posted in Mac,Stata

  • Ulrich

    Pretty cool extension to Timothy Beatty’s bundle.

    However, I get mixed up with file location and directories, what do you suggest?

    Thanks in advance,

    p.s. Looks like I’ll join the LSE for the 1 in 1+3 this Fall. =)

  • Hi Ulrich. Good to hear you’re coming to LSE. Can you explain your file location and directories mix-up in more detail? Not sure I understand.

  • Pingback: Stata bundle for TextMate |

  • George,

    Thanks for sharing! I took the liberty to post a bundle that includes your command. In case anyone wants it, you can download it here.