Customizing Your Ruby IDE
In the time since we launched the first public beta of Ruby In Steel last April, we’ve received numerous requests from people who really, really can’t live without a certain special ‘cool little feature’ from some other editor or IDE which they’ve used previously.
Some of these requests were for major features (debugging, Rails tools and so on) which were already on our published Road Map and which have since been implemented in later releases of the software. But many others were for what seemed, at first sight, to be pretty minor things – certain colour schemes, automated code expansion, quick navigation tools and so on. However, from personal experience, I know that the things that seem minor to me are exactly the things that seem major to someone else – and vice versa. In short, no matter how much power lies ‘under the hood’, if the IDE doesn’t do that ‘special thing’ that you use all the time in some other IDE, then it just isn’t good enough…
Macros? Never Used ‘Em!
We’ve put a good deal of effort into adding as many configuration options as possible: in addition to all the usual Visual Studio colouring options, we’ve added a raft of extra options to colour everything from a Rails tag to a Ruby instance variable. As I’ve explained in previous posts, we’ve also added auto-expansion snippets to the Ruby editor and we’ve written a dedicated Ruby snippet editor to make it easy to write your own snippets just by filling out the fields on a form. But no matter how many tools and options we supply there will, inevitably, still be occasions when we haven’t made feature X work quite the way that user Y really, really wants it to work.
After a while, I realised that the real solution to user configurability was the Visual Studio macro language. With VS macros you can do everything from automating repetitive tasks to creating whole new editing and project management capabilities.
So why then, if macros as so darn’ good, have I never used them?
As soon as I delved into the Macro IDE, the answer to that question became readily apparent. Visual Studio macros are horrendously complicated. I mean, it’s simple enough to record a macro to play back some text on command (Ctrl+Shift+R records and Ctrl+Shift+P plays back);but when you want to take real control over the environment – finding and selecting text patterns, locating and opening a specific file in the Solution Explorer and so on – things get a whole lot more difficult.
The macro language itself is not hard to master (it’s Visual Basic) but the automation model certainly is! When I started coding macros, I found that most of my time was being spent searching the help system rather than writing code. I had to learn all about the DTE (Development Tools Environment) interface; in order to handle the Solution Explorer I had to find my way through a maze of classes and interfaces – Projects and Project Items, SolutionFolders, UIHierarchy objects, UIHierarchyItem objects and more besides. When editing a document, there was a whole set of other classes Documents, TextDocuments, TextSelections, EditPoints, TextPoints and so on. Many of these sound more or less the same (I still find myself getting confused between Documents and TextDocuments, EditPoints and TextPoints) but they each have different features, properties, methods and unexpected side-effects!
The Macro Library
Pretty soon I realised that if I was having so much trouble getting going with macros, it was surely unrealistic to expect users of Ruby In Steel – who, on the whole, probably just want to get on with programming Ruby – to spend so much time grappling with VB and the DTE.
My solution has been to start writing a small library of utility functions. For example, I’ve written a macro called SurroundWithTags(). This lets you mark off a block of code in an RHTML file and enclose it between whichever tags you wish. For example, to surround it with standard Rails ‘embedded Ruby’ tags, you’d call the method with this single line of code:
SurroundWithTags("<% ", " %>", True)
The third parameter (True in the code above), is a Boolean which lets you decide whether you want to put the opening tag at the start of the opening line (i.e. at the far left margin) or at the start of the selection itself (which may be indented from the margin).
Another function called SurroundEachLineWithTags() encloses each separate line in a marked block between its own set of tags – that is, one pair of tags for each line of code. By making use of these two functions, you can easily specify any set of tags – standard HTML ones such as
<div></div> or entirely non-standard ones such as
<MyTag></MyTag>. The point is that, in order to do this, you only have to write a one or two-line function; you don’t have to mess around with all the stuff in the automation model.
I’ve written a batch more ‘library’ functions that you can use to create other Ruby and Rails macros. Naturally, having written functions to add tags to marked blocks and lines, I’ve also written functions to remove tags marked blocks and lines; there are also macros to add standardized comment blocks to methods and documents; and there are macros to list all the files in a project and all the methods in a code file. There are also some macros to implement a requested feature: namely, the ability to move instantly between the controller and its view (and back again) in a Rails project.
I’ll have more to say on some of these in my next blog entry…