Snippet Pipes
September 16th, 2008
The latest update adds an extension to the snippet format, so that you can pipe the contents of individual tabstops through shell commands. This makes it possble for snippets to be far more interactive.
The syntax is pretty straightforward. Here is a simple example that allows you to directly evaluate ruby code:
${1:ruby code|ruby -e "print eval STDIN.read"}
If this snippet is bound to the tabtrigger “ru”, then pressing ru[TAB]1+2[TAB] will result in 3 (without leaving any trace of the intermediate steps). Very handy for doing quick calculations without having to do a mental shift and since you have access to the full language you can do far more than simple arithmetic.
The equivalent snippet for python would be:
${1:python code|python -c "import sys; print eval(sys.stdin.read())"}
The commands are not limited to just reading from stdin. They have access to all the standard environment variables, plus a few snippet specific ones:
- TM_SNIPPET : contains the entire snippet
- TM_TABSTOP_n: contains the contents of the individual tabstops
This means that you can make snippets that react on quite complex input from the user. Here is a simple example of a snippet that draws a box in a user defined size:
${0:Draw box ${1:10} times ${2:10}|"$TM_BUNDLE_SUPPORT/starbox.rb"}
It works with the following script placed in the bundles support dir:
#!/usr/bin/env ruby
width = ENV['TM_TABSTOP_1'].to_i
height = ENV['TM_TABSTOP_2'].to_i
height.times do
width.times {print “*”}
print “\n”
end
The content is piped to the command at the moment you tab out of a tabstop. The one exception is tabstop zero (the ender tabstop). Since this completes the snippet, the piping happens on entry. In the above snippet, this is used to replace the entire snippet text with the user defined box.
This extension of the syntax is currently specific for e. But if it sees enough use then we can hope that it becomes supported in TextMate as well.