Matt Rajca

blog projects github twitter email

Adding Code Completion Support to TextMate Bundles

July 09, 2011

Code completion isn't a prominent feature in TextMate, but it exists. If you enter some text and hit Escape repeatedly, TextMate will cycle through all available code completions. Unfortunately, this only works with the Objective-C and PHP bundles, and all functions and methods suggested exclude parameter lists. Compared to the code completion system in Xcode 4, this feels lacking.

After doing some exploring, I discovered that the PHP bundle does something clever: if you hit Option+Escape or select the "Completions for Word..." menu item from the bundle's action pop-up, TextMate will present a menu of available code completions.

TextMate Code Completions

What's more, once a completion is accepted, the name of the function and its parameters will be inserted. You can even tab through each parameter, just like in Xcode! After digging around in TextMate's Bundle Editor, I was surprised to find that the code to make all of this happen is only 5 lines long:

    
    #!/usr/bin/env ruby -wKU
    require ENV['TM_SUPPORT_PATH'] + '/lib/osx/plist'
    require ENV['TM_SUPPORT_PATH'] + '/lib/ui'
    
    choices = OSX::PropertyList.load(File.read(ENV['TM_BUNDLE_SUPPORT'] + '/functions.plist'))
    TextMate::UI.complete(choices, :initial_filter => ENV['TM_CURRENT_WORD'], :extra_chars => '_')
    

It turns out TextMate has built-in support for this menu-based code completion UI in its ui.rb support file -- and it works pretty darn well. The completions are stored in a referenced plist file, whose structure is pretty self-explanatory:

  
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <array>
        <dict>
            <key>display</key>
            <string>ArrayMin</string>
            <key>insert</key>
            <string>(${1:const variant &amp; src[]}, ${2:unsigned int idx}, ${3:unsigned int len})</string>
        </dict>
    </array>
    </plist>
    

The value of the display key contains the name of the code completion item as it will appear in the list. Additionally, the value of the insert key contains an ordered list of parameters, which will be inserted whenever a code completion is accepted.

Building on top of this, I managed to add menu-based code completion support to a NXC bundle I'm working on, all in a matter of minutes. It's a shame that so few TextMate bundles utilize this hidden gem.