Increasing Productivity with Textmate's New tm_dialog
TextMate has been one of those tools that has significantly increased my productivity. Allan has managed to create an editor that is great for Designers and Unix geeks alike, and not to mention a vibrant and helpful community who seem to thrive on making contributions. Allan has recently upped the ante with the recently released tm_dialog; a new dialog system for commands. I’ve already come up with a use for it that helps me get my job done faster. In addition to that, I’ve made use of the Drag Command which is also helping me clean up my workflow.
Get to know tm_dialog
If you have yet to check out Allan’s screencast on tm_dialog, I encourage you to do so. He shows how powerful it is by using Interface Builder to create a dialog for viewing subversion logs; Something I do regularly. In addition to that, he’ll be creating a complete series that helps us make the best use of tm_dialog.
Cleaning up the mundane task
While editing CSS files, I find myself clicking through the project drawer looking for image file names and locations time and time again. When I do find the image I’m looking for, I end up repeatedly writing code like this:
#header {
background: url(../images/hdr-bg.gif) no-repeat;
}
Now Textmate offers a variety of ways to keep you from having to manually type this out. You could create a snippet that triggered when you typed bg that would do most of the typing for you, but you still have to sort out the path or what not. Using a drag command, we can speed up this process.
Using Drag Commands
What I want to do here is to drag an image file from the project drawer and drop it onto the document and have TextMate type all the url stuff for me and figure out the relative path to the image. Thats great and all, but what about the no-repeat, repeat-x, etc.? Again, there are a number of ways to do this as well, but if your like me I usually have a common naming convention I use for tiling images. If an image tiles, I usually name it something like hdr-bg-tile.gif, or if it tiles on the x axis, I name it something like hdr-bg-xtile.gif. The same applies for the y tile.
Wouldn’t it be great if TextMate could figure out all this for us and the only thing we needed to do was just drag the image onto the document? Well, it can, and here is a short video of this in action:
Nice eh? If you want this behavior, just create a new drag command and pop in the code below. Set your file types (gif, png, jpg, etc) and scope to source.css.
#!/usr/bin/env ruby
image = ENV['TM_DROPPED_FILE']
image_name = File.basename(image)
repeat = ' no-repeat'
if /(xtile|tilex|ytile|tiley|tile)\./ =~ image_name
unless $1.nil?
repeat = case $1
when 'xtile', 'tilex' then ' repeat-x'
when 'ytile', 'tiley' then ' repeat-y'
when 'tile' then ''
end
end
end
print %(url(#{image})#{repeat})
Using tm_dialog to create a menu with project images
One of the cool features of tm_dialog is that we now have the ability to create custom menus. With this in mind, I wanted to stop the hunt and peck process–Hunting for images in the project drawer, and typing the required information to make that image display in css. I want to hit a key combination and have TextMate present me with a menu of images it found in the project directory, when I select an image from the menu, it should fill in all the required info. And here it is:
I used Allan’s example for tm_dialog posted here and came up with this bit of Ruby: UPDATE: Modified to ignore .svn files.
#!/usr/bin/env ruby -wKU
SUPPORT = ENV['TM_SUPPORT_PATH']
DIALOG = SUPPORT + '/bin/tm_dialog'
require SUPPORT + '/lib/escape'
require SUPPORT + '/lib/plist'
require 'pathname'
require 'find'
images = []
Find.find(ENV['TM_PROJECT_DIRECTORY']) do |f|
file_name = File.basename(f)
if /\.(gif|jpg|png)$/ =~ file_name
images << {
'title' => file_name,
'path' => Pathname.new(f).relative_path_from(Pathname.new(ENV['TM_FILEPATH']).parent).to_s
}
end
end
abort if images.empty?
plist = { 'menuItems' => images }.to_plist
res = PropertyList::load(`#{e_sh DIALOG} -up #{e_sh plist}`)
abort unless res.has_key? 'selectedMenuItem'
print %(url(#{res['selectedMenuItem']['path']}))
This code uses Find and Pathname to get the images and their path and in turn stores those values in a Hash. When we have the hash built, we create a property list from it, using menuItems as the root key for the array of image information we just build.
After we have the plist, we can pass it on to the actual dialog in the next line. If the user selects an item from the menu the resource will have the key selectedMenuItem and then we’ll take that and ask for the path value which is wrapped up in the correct CSS syntax for referencing images and then printed to the document.
As you can see, this is some pretty nice stuff and TextMate makes it dead simple to increase your productivity and extend it into an editor that is perfect for you.
(P.S. Sorry for the video size, I’m experimenting with Revver, whom I’ve recently been doing some work for.)
Sorry, comments are closed for this article.


Discussion
Since tm_dialog can support loading Interface Builder NIB files, it’d be awesome if had a dialog that displayed the images it found.
Video size seems ok for showing the examples, imo.
damn, that is tight…
videos were fine for me.
I’ve been using TextMate as my primary editor (sadly I still have to swim through the soup that is Dreamweaver occassionally), and the ammount of functionality wrapped up in elegant solutions like this is amazing.
So much so that I actually bought a Mac, with my main justification being TextMate.
Slick.
I also just recently posed a couple new commands that use tm_dialog’s menu stuff. Screencasts and all.
The one is for English Word Completion. And the other is for Filepath Completion.
check it out: subtleGradient.com
Wow I tried out the program and it really does work well, great find thanks.
With the code above for tm_dialog, what type of command do you create and how do you map it to the code? I am quite new to this :)
Nevermind, I ended up figuring it out by doing New Command, Input -> None, Output -> Insert as Snippet :)
@kamal: There is an image browser dialog in TM that shows a preview. I really just wanted a quick list of images because most of the time I know what they are or know most of the file name and just want to be sure.
This is brilliant Justin. Finding images and digging through Textmate projects for images is a bti of a pain. Love both commands and they’re going to be welcome additions to my workflow.
would it be possible to translate what he’s done so far, into a file filter system like TextMate has using Apple + T to jump to files in a project but filter just images so you can pick which one to insert?
This is fabolous! I’m also experimenting with some tm_dialog ang Interface Builder! It’s very simple. Now with your code I try more solutions for my idea!
The vids do not work for me. Anybody else have that problem?
I think you meant to type “upped the ante.” ;-)
You know, thats not the first time I’ve put poor annie in harms way. ;-)
Hi Justin, Just wanted to let you know that I took up where your image insert command left off… I’ve posted one to the TM list that adds your name-based repeat selector with a conditional check for scope and inserts the appropriate information depending on whether you’re in source.css or all the way inside of the single quotes of a url(’’). It also grabs and inserts image width and height automatically if it’s creating a full rule or declaration block. If you want a copy and don’t catch it on the list, email me. Great screecasts and thanks for the inspiration!
Revver videos don’t work here, either. I get the initial logo animation like it’s loading, then black for a while, then an advertisement.
Firefox 2.0 on OS 10.4.8.
Nice work Brett. :-)
The best idea since T.B. Lee.
But I cannot solve the following problem: I want to get the id of a clicked element. It has an id. ;-))
var Rules = { ’.bildrechts:click’ : function(element) { var app = element.id; alert(app); }}
The alert shows everytime an empty string. ;-((
Does someone know if the Prototype documentation project is dead already? A long time ago there were rumours about such an effort, and also about protoype 1.5 that is still not final. I fear that the whole Prototype thing is burried in silence. jQuey for example moves much faster. Can someone clarify; are my concerns right?
It’s not, stay tuned…!
Have a look at the changelog, things are moving!