WARNING: This blog entry was imported from my old blog on blogs.sun.com (which used different blogging software), so formatting and links may not be correct.
I've received several requests for support for TextMate-style snippets. TextMate is a very popular editor among Ruby developers, and a lot of its power comes from its code snippet functionality. Snippets are basically identical to what NetBeans calls "Live Code Templates". The code templates are live in the sense that when you insert the template, you're in a mode where you can jump from one logical section of the template to another, and edits in one section can automatically be updated in other sections.
I've just implemented an import mechanism for TextMate bundles. Point at your own bundles (or even the ones distributed with TextMate, although I don't know what the legal issues are with that), and choose import.
This will convert all* the snippets into NetBeans Live Code Templates (*=for some values of all).
There are two features in TextMate snippets that are not supported:
- Command execution. A snippet can contain a `shell command` (in backquotes), and at template evaluation time, the command will be executed and the result inserted. In the snippet bundles I looked at, this was used only for a single thing: inserting parentheses on a conditional basis. So I just made the import handle parentheses directly instead.
- Regular expression replacement. A template can perform regular expression replacement on different instances of the parameters. I can't even tell exactly how this is supposed to work, but for now, I skip snippets that do this.
TextMate is essentially a text editor; it doesn't (as far as I can tell, having never used it but having read their snippets and macros in detail) have any real semantic information about the code. Therefore, doing complicated text processing with regular expressions is the Way of TextMate to achieve logical code operations. Live Code Templates on the other hand can take advantage of all the information the IDE has about the code.
I've added a bunch of logical code template variables you can use in templates. Rather than try to reproduce the regular expression operations
of TextMate's snippets engine, I would like to create logical Ruby operations for the code templates and use those instead.
Here are some examples of what is possible with this mechanism. None of the imported snippets use these variables, but the imported snippets are useful in their own right - especially for those of you with muscle memory.
${unusedlocal defaults="i,j,k,x,y,foo,bar"}
This will evaluate to an unused local variable in the current scope. It will try to use the provided suggested names, in order. It checks whether each one is already in scope, and if so, tries the next candidate. (If none succeed, it starts appending numbers to find a unique name. If there are more Rubyish ways of generating unique variables, please let me know.)
First, we create the template, naming it "dob":
Then, in some method I want a do-block. I just type "dob" and hit Tab, and voila:
It inserts a do-end block. When it comes to the block variable, it has looked at the context and discovered that the first two preferred alternatives, i and j, are both taken - so it chooses k. This shows the advantage of using semantically aware code templates - you don't accidentally alias an existing variable. This wouldn't be a problem in Java, where it would complain that your new variable already exists in scope, but in Ruby, this is valid (and sometimes, but not usually, what you want.)
As another example, here's a silly template which spits out a hash that defines a bunch of local context:
Let's say I have the following silly file, and type "ctx":
If I now hit tab, I get this:
I will now be able to walk through (with the tab key) each of the variable sections and edit them. For an example like this, it's likely that we don't want these things to be edited by the user - so just add editable=false on each such variable (e.g. ${class editable=false}) and they will be processed but not edited by the user.
One of the things that makes this really powerful, is that it uses a lot of the context information the IDE has about your program. In this example, computing the super class of the current class isn't that hard - and a fancy Ruby shell script executed might be able to pull it off. But if I was simply redefining an existing class, let's say Integer
, and there is no local reference to Integer's parent class, the live code template will spit out Numeric
. Yes, it looks in the index.
Call for Help
As I've shown, the basic machinery is there now, but what we really need is a set of code templates to be bundled with the IDE. Some will be
simple substitutions or linked variables, but we should be able to come up with some much stronger ones. Please let me know what kinds of
logical parameters you can take advantage of. For example, perhaps a parameter which evaluates to the require statements necessary for
the classes referenced in the file? Or a parameter which looks for database table names in the database? Perhaps some simple transformations which
produce a constant name or a method name (upcasing and downcasing) from some other symbol? There are a lot of possibilities here,
but since I'm not a real Ruby programmer I'm not the best person to dream this stuff up. If you can look at snippets you have written, import them into NetBeans, optionally edit them to add more semantic analysis if appropriate, and contribute them, I'd be very thankful!
Also, I have never used TextMate, so I would appreciate feedback on whether the templates work the way they do in TextMate, or if I misunderstood something from just reading the snippets themselves. Bug reports (preferably via the issue tracker) are much appreciated.
So, where can you get this stuff? I just integrated everything, but the Live Code Template management is not in stock NetBeans; it's in an optional download called "CodeTemplateTools" (in contrib/CodeTemplateTools), written by Sandip Chitale. More info about this module is
here. I have built an NBM you can install directly - just download the module bundle file, then install it via the IDE via the Update Center (in the first panel choose manually downloaded NBM). Note however that you must have the other IDE fixes as well; they should be live on deadlock.nbextras.org soon but probably won't hit the Update Center for a couple of days. (I'll try to make the slim IDE bundle the tools). As always, see the wiki for installation instructions. Once you have installed the Code template tools, look for "Show Templates..." in the Edit menu. The import UI is still a bit rough - no progress bar etc - I'll worry about that later. There's one more rough spot: the "|" character must be escaped (by typing it twice) because historically, NetBeans used "|" to indicate the cursor position. There is the logical variable ${cursor}
for that now, but there's still some issues we need to resolve in this area.