irbrc for the runtime tramp

I’m taking a break from the Rubinius for the Layman series. I don’t know why my posts always spiral into multi-thousand words essays :-) Even worse, when I try to write about Rubinius it’s so easy to get into ratholes and start fiddling, poking at and exploring this wonderful beast. All of that instead of writing, of course.

Tonight’s fiddling led me to playing around with my .irbrc file. I guess we’ve all searched for examples of config files for IRB at one time or another. When you spend a lot of time into your interactive console, you naturally end up wanting to tweak it to your liking.

However you’ll start having problems as soon as you start fooling around with the different runtimes. Or when you share your irbrc between different machines. Maybe even on different OSes. Either some gems are unsupported or you haven’t installed them yet (and don’t necessarily care).

So tonight I tried to fix that problem. My solution is only a small method that I define in my irbrc, so I’m not sure it’s worth putting it on github yet :-) Let me know what you think.

Presenting tramp_require

Usage

When my irbrc requires something just so I don’t need to do it manually:

tramp_require 'pp' #=> true/false (same return value as a normal require)

Outcome if the gem is not installed:

** Unable to require 'wirble' 
--> LoadError: Did not find file to load: wirble

And you IRB loads without a problem (just without the gem pre-loaded).

When I require something I actually use in my .irbrc:

tramp_require('wirble') do 
  Wirble.init(:skip_prompt=>true) 
  Wirble.colorize 
end

If the gem is loaded successfully, the block is executed.

If the gem isn’t loaded successfully, the block’s not executed and the same warning message is shown.

Note that the user code passed in the block is not being rescued: if it your code fails, it’s your problem :-)

Implementation

Here I’ll paste 2 equivalent implementations. The first one is a clean and understandable version (also on pastie):

def tramp_require(what, &block) 
  loaded, require_result = false, nil 

  begin 
    require_result = require what 
    loaded = true 

  rescue Exception => ex 
    puts "** Unable to require '#{what}'" 
    puts "--> #{ex.class}: #{ex.message}" 
  end 

  yield if loaded and block_given? 

  require_result 
end

This second version is the one I actually use, if I set the debug variable to false the result is the same as the previous implementation. If I set it to true, I get much more information, including the full backtrace of the exception (also on pastie):

$debug_irbrc=false 

def tramp_require(what, &block) 
  loaded, require_result = false, nil 

  begin 
    puts('', "requiring #{what}") if $debug_irbrc 
    require_result = require what 
    loaded = true 
    puts "successfully required #{what}" if $debug_irbrc 

  rescue Exception => ex 
    puts "** Unable to require '#{what}'" 
    exception_details = "#{ex.class}: #{ex.message}" 
    if $debug_irbrc 
      ex.backtrace.reverse.each{|l| exception_details < < "\n   #{l}"} 
    else 
      exception_details.insert(0, "--> ") 
    end 
    puts exception_details 
  end 

  if loaded and block_given? 
    puts "executing block for #{what}" if $debug_irbrc 
    yield 
  end 

  require_result 
end

Feel free to use these snippets as you see fit :-)

The obligatory full paste of my irbrc is available on pastie, for the curious.

One word of warning, however. I’m guessing some of you will rename tramp_require to something more boring. Just don’t rename it to irb_require. IRB already defines a method named this way.

Comments