Beyond The Ruby Console
Right from the start, RiS has had a Ruby ‘console’. This is a simple looking interface which allows you to communicate with Ruby just as if you were running Ruby from a command prompt. However, the console is actually part of the IDE and can be docked, tabbed or ‘floated’ like many other IDE windows.
While it looks quite simple, it’s really pretty complicated underneath – the complexity comes from getting the console to run reliably and particularly never, ever to ‘freeze’. Freezing – or ‘locking-up’ – occurs not because the Ruby program has gone into a loop or something like that, but because the Ruby program has decided to dump several GB of data into the console’s communication channel. And for one reason or another, the console can’t read it – typically because it has replied to the first part of the GB dump with a heap of garbage of its own. And of course the CTRL-C command that will get you out of the trouble is parked right at the end of that. It’s all too easy to do.
In fact, that’s only one problem. There are certain race conditions in Windows which will occur if you use the ‘standard input’ and ‘standard output’ channels in a simplistic manner. There are usually two ways round this. The first is to use ‘overlapped’ or asynchronous I/O, but this can be tricky with managed memory and garbage collection issues. The other way is to use synchronous I/O but implement queue buffers which allow both the Ruby program and the console input to work more or less independently.
I chose the latter approach and, so far, I haven’t had a single ‘lock-up’. The console window in the IDE might look like a ‘DOS box’ it most certainly isn’t. It’s actually a Visual Studio graphical ‘tool window’ hosting a ‘text buffer’ COM object. It has much more to do with the core text editor that you use for C# or Ruby than with the command prompt that you get from running a ‘DOS box’. For example, one of the features of the Ruby console is a ‘command history’ which is actually pasted back into the text buffer and so into the graphical tool window when you retrieve a command. All in all, the console is a pretty complicated animal.
And that’s why there’s only been one of them – till now.
The Honorary Consoles
For version 1.2, we’ve implemented a further five consoles. There’s a Rails console that runs the ‘scripts/console’ command, a rake console, a generate console, an IRB console and a generic ‘script’ console – all of which dock nicely and which can have their own user defined color schemes and fonts.
Of course you can still create a real command window independently of the IDE as you can now. But the advantage of these four consoles is that the output and display are much more tightly integrated into the IDE. In particular, the rake and generate consoles aren’t ‘fire-and-forget’ any more – the error messages and output are clearly available for you to see and if there’s any interaction required, they work just like the original Ruby console.
On a minor side point, the original Ruby console was one of the first things I wrote when we started RiS and I had something of a shock when I re-visited it. I really didn’t know what I was doing with the Visual Studio IDE back then! But even now, I’m still finding things out on a daily basis – Visual Studio is a remarkable system more akin to an operating system such as Windows 3 (think ‘co-operative multitasking’) than a simple toolkit. It’s complicated but it certainly does repay careful study and hard work.