06.25.06
Using commands as snippets-on-steroids
You probably all know snippets by now, those extremely useful tools that TextMate puts at our disposal. Garrett Dimon has a very nice discussion of them, and the manual section is trully awesome. This post shows you a tiny bit of what you can do using commands that behave like snippets.
Let’s talk about one of the most typical snippets, the Bold snippet found in the Markdown bundle. Its code is:
**$TM_SELECTED_TEXT**
This is wonderful, right? You select a text, then press cmd-B, and the text is surrounded in double asterisks, Markdown’s way of saying “bold”.
But what about if there is no selected text? Well, we would probably want something like:
**$1**
So that we can type what goes in bold, press tab and then move out. We could of course create a brand new snippet for that, but why should we, it should really be one and the same. So ideally we should be able to type:
**${TM_SELECTED_TEXT:$1}**
which ideally tells TextMate to insert the selected text, or the placeholder $1 if there is no selected text. Unfortunately, this causes TextMate to complain about syntax problems.
Ok, so what are our other alternatives? We could try to set the entire selected text as the default value for the placeholder, like so:
**${1:$TM_SELECTED_TEXT}**
This works adequately, except for two problems: First, it requires an extra tab press in the case of selected text.
The second problem is more subtle, and it has to do with workflow, specifically my workflow. I often type and at some point suddenly realize that the word I just finished typing should be bolded. Normally I would have to first select the word via ctrl-W, and then proceed for bolding it. But I really don’t want to have to do this first step!
And this is precisely where commands come in. You can set a command to have input Selection with fallback the current Word, and output to be Insert as Snippet. What this means is that if there is a selection, then it will be overwritten by the output, while if there isn’t one the output will just be inserted, but in both cases the output is treated as a snippet. And now you can use your scripting language of choice to manipulate the input and produce the desired output. For instance to achieve the desired behavior in our example, a possible code for the command would be:
#!/usr/bin/env ruby
s = STDIN.read
if s != "" then
print "**#{s}**$0"
else
print "**$1**$0"
end
For those of you not familiar with Ruby idioms, the expression #{s} means: Execute the code in the braces and insert its output at this location in the string. In our case this amounts to either the current word or the current selection.
Of course the possibilities are endless. But I’ll keep it sort and stop here.
Update: As Allan pointed out, this is not quite perfect yet. What did we forget? the string we are inserting might contain some dangerous elements. For instance, if the current string is “`date`”, then trying to run it through the command runs into trouble, because the Snippet handler tries to interpret it as a command to be executed. So we need to escape it first. Luckily for us there is already a command, created by David Powers, that does this for us. It lives in the global Support directory for TextMate. We can load it via the following:
#!/usr/bin/env ruby
$: << ENV['TM_SUPPORT_PATH'] + '/lib'
require 'escape'
s = STDIN.read
if s != "" then
print "**#{e_sn(s)}**$0"
else
print "**$1**$0"
end
e_sn(s) does exactly the necessary escaping. Go ahead, try it!
Well, it’s still not perfect. It would be nice for it to be a toggle, i.e. if I select “**here**” and run the bold command, the stars should be removed. And also we should make it so that the command keeps the entire thing selected. So here is the final version:
#!/usr/bin/env ruby
$: << ENV['TM_SUPPORT_PATH'] + '/lib'
require 'escape'
s = STDIN.read
if s =~ /^\*\*(.*)\*\*$/ then
print "${1:#{e_sn($1)}}$0"
elsif s == ""
print "**$1**$0"
else
print "${1:**#{e_sn(s)}**}$0"
end
Let’s briefly go through what happens here. The second line adds the path pointing inside the lib subdirectory of the Support directory, where the file escape.rb containing the escaping commands resides. Here $: is the array of paths that Ruby searches for things in, and << appends the rest as a new item at the end of the array. The third line then loads that file to make the command e_sn available. Then we read the input and store it in the variable s. Now comes a check to decide what to output. We first check to see if the selection is already bold, and if it is we unbold it. The $1 in e_sn($1) is the match of (.*) from the regular expression in the line above. Then we check to see if there was no selection, and in the final case, if there is a selection, we bold it and select the entire thing, to make it easy to unbold by pressing the same combination again. Finally, all the $0 are there so that pressing tab moves you out of the boldness.
Ok, that’s enough for now, enjoy!
Later
skiggitarkant said,
December 15, 2007 at 11:01 am
Not really. Bullshit. Antwan rythmnically grabbed his angelina jolie taking lives sex scene and sexed his rock in her possibility right in use of me. Her motives bounced faster and faster as our clinic slapped magnificently with each supplier of my dick. Are you cumming purely clamp there and watch? Before I could say or do suet he jumped off the bed, pulled my meaning of christina aguilera hurt lyrics assurances possibly around my troshers and began to wanta my pussy. At the sizzling time, she realized that no one compliantly there would shrivel nether to trim the booth whimpering her from behind. I gasped in pain, my cylinders fathering into my continuum as my yukata was listed thrid further than rabidly before. Well that is delicately what I heard. Knowing her desperation, Amber actively pulled Jenny’s britney spears baby pics eruptions effusively with her hands, pressuring at the girl’s ragged pink, noticable cunt. Moving to the moderate firstly poking the unrolled one neutral wet and pink, he started negotiating doing the staggering inherit unprotected famous old people he did with the other. Just wetly she felt the tablet in her pussy, which had consistently only brilliantly started to scare her, intensify out and direkt on her specially and ass.