My .irbrc for console/irb

I recently discovered that I can create a .irbrc file to run setup for
my irb/console. I am in love.

My current .irbrc is:

require ‘irb/completion’
require ‘map_by_method’
require ‘what_methods’
require ‘pp’
IRB.conf[:AUTO_INDENT]=true

Explanation of the different libraries:
http://drnicwilliams.com/2006/10/12/my-irbrc-for-consoleirb/

Does anyone any interesting things in their .irbrc file?

Nic

On 12/10/06, Dr Nic [email protected] wrote:

I haven’t used it but Wirble(http://pablotron.org/software/wirble/)
looks pretty cool.

Farrel

Farrel L. wrote:

On 12/10/06, Dr Nic [email protected] wrote:

I haven’t used it but Wirble(http://pablotron.org/software/wirble/)
looks pretty cool.

Very nifty indeed.

On 10/12/06, Dr Nic [email protected] wrote:

Does anyone any interesting things in their .irbrc file?

I don’t know why I hadn’t thought of it before but I just added:

show_regexp - stolen from the pickaxe

def show_regexp(a, re)
if a =~ re
“#{$`}<<#{$&}>>#{$'}”
else
“no match”
end
end

Convenience method on Regexp so you can do

/an/.show_match(“banana”)

class Regexp
def show_match(a)
show_regexp(a, self)
end
end


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/

Nice, thanks!

You may find it useful to extend your #what? with #what_returns?(x)

[1, 2, 3].what_returns?(1) #=> [ :first ]

Used in some method browsers in Squeak. Could be extended in all kinds
of
ways - state change, parameters,…

On 10/12/06, Dr Nic [email protected] wrote:

I recently discovered that I can create a .irbrc file to run setup for
my irb/console. I am in love.

Does anyone any interesting things in their .irbrc file?

Sure, see

http://blog.nicksieger.com/articles/2006/04/23/tweaking-irb

Cheers,
/Nick

On Thu, 2006-10-12 at 21:32 +0900, Dr Nic wrote:

I recently discovered that I can create a .irbrc file to run setup for
my irb/console. I am in love.

Does anyone any interesting things in their .irbrc file?

I have these to help keep output manageable:

class Array
alias :__orig_inspect :inspect

def inspect
(length > 20) ? “[ … #{length} elements … ]” : __orig_inspect
end
end

class Hash
alias :__orig_inspect :inspect

def inspect
(length > 20) ? “{ … #{length} keys … }” : __orig_inspect
end
end

This for history (I believe I got it from Rubygarden):

HISTFILE = “~/.irb.hist”
MAXHISTSIZE = 100

begin
if defined? Readline::HISTORY
histfile = File::expand_path( HISTFILE )
if File::exists?( histfile )
lines = IO::readlines( histfile ).collect {|line| line.chomp}
puts “Read %d saved history commands from %s.” %
[ lines.nitems, histfile ] if $DEBUG || $VERBOSE
Readline::HISTORY.push( *lines )
else
puts “History file ‘%s’ was empty or non-existant.” %
histfile if $DEBUG || $VERBOSE
end

Kernel::at_exit {
  lines = Readline::HISTORY.to_a.reverse.uniq.reverse
  lines = lines[ -MAXHISTSIZE, MAXHISTSIZE ] if lines.nitems >

MAXHISTSIZE
$stderr.puts “Saving %d history lines to %s.” %

    [ lines.length, histfile ] if $VERBOSE || $DEBUG
  File::open( histfile, File::WRONLY|File::CREAT|File::TRUNC ) {|

ofh|
lines.each {|line| ofh.puts line }
}
}
end
end

And this for RI (again, from Rubygarden or someone’s blog, I forget

which):

def ri arg
puts ri #{arg}
end

class Module
def ri(meth=nil)
if meth
if instance_methods(false).include? meth.to_s
puts ri #{self}##{meth}
else
super
end
else
puts ri #{self}
end
end
end

On 10/12/06, Dr Nic [email protected] wrote:

Explanation of the different libraries:
http://drnicwilliams.com/2006/10/12/my-irbrc-for-consoleirb/

Does anyone any interesting things in their .irbrc file?

Mine is rather large and in flux right now but I will post a few
nuggets from it bellow:

require ‘rubygems’

Very basic prelude of enhancements for Object

module ObjectEnhancer

def clone!
self.clone rescue self
end

def tap
yield self
self
end

def _
yield if block_given?
nil
end

end

class Object
include ObjectEnhancer
end

Lazy loading prety print support

class Object
def pp(*a, &b) # pass the block just-in-case this changes.
require ‘pp’
pp(*a, &b)
end
end

Tab completion

require ‘irb/completion’
IRB.conf[:USE_READLINE] = true

Histories

require ‘irb/ext/save-history’
IRB.conf[:SAVE_HISTORY] = 1000
IRB.conf[:EVAL_HISTORY] = 100

Prompts

IRB.conf[:PROMPT][:CUSTOM] = {
:PROMPT_N => ">> ",
:PROMPT_I => ">> ",
:PROMPT_S => nil,
:PROMPT_C => " > ",
:RETURN => “=> %s\n”
}

Set default prompt

IRB.conf[:PROMPT_MODE] = :CUSTOM

Simple ri integration

def ri(*names)
system(“ri #{names.map {|name| name.to_s}.join(” “)}”)
end

fresh irb. It uses an at_exit handler to yield it a block is given.

def reset_irb
at_exit {exec($0)} # first registered is last to run
at_exit {yield if block_given?}

From finalizer code in irb/ext/save-history.rb… very ugly way to

do it :S… who wants to rewrite irb?
if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0
if hf = IRB.conf[:HISTORY_FILE]
file = File.expand_path(hf)
end
file = IRB.rc_file(“_history”) unless file
open(file, ‘w’) do |file|
hist = IRB::HistorySavingAbility::HISTORY.to_a
file.puts(hist[-num…-1] || hist)
end
end

Make irb give us a clean exit (up until our at_exit handler above)

throw :IRB_EXIT, 0
end

clear the screen… with some self destruction :wink:

def clear
eval “def clear; print #{clear.inspect} end”
clear
end
private :clear

Simple webserver (Loazy loading)

def serve_files(opts = {})
require ‘webrick’

opts[:host] ||= Socket.gethostname
opts[:dir] ||= Dir.pwd
opts[:port] ||= opts[:dir].hash % 1000 + 10000
opts[:log] ||= Nop.new # hidden and simple.

server = WEBrick::HTTPServer.new(
:Host => opts[:host],
:Port => opts[:port],
:DocumentRoot => opts[:dir],
:Logger => opts[:log]
)

trap(“INT”) {server.shutdown}

puts “Serving "#{opts[:dir]}" at
http://#{opts[:host]}:#{opts[:port]}/”
server.start
nil
rescue
puts “Failed to start server! See $webrick_error for the exception.”
$webrick_error = $!
nil
end
private :serve_files

SSH support. Needs a lot of work still but it is nice to have.

This was just a 5 min hack. Thanks goes to Jamis for the

nice library.

Note that you must sleep to have the event loop run.

def ssh_session(opts = {})
puts “Note: You must ‘sleep’ in order for the event loop to run in
irb.” if require ‘net/ssh’

dynamic_session_class = Class.new do
@@default_opts = {
:user => ENV[‘USER’] || ENV[‘USERNAME’],
:port => 22
}.freeze

def initialize(opts = {}, aux = {})
  opts, opts[:host] = aux, opts unless Hash === opts
  opts = aux.merge opts
  opts = @@default_opts.merge opts

  @shutdown = false
  @queue = []

  ready = false
  Thread.new {
    begin
      Net::SSH.start(opts[:host],
        :username => opts[:user],
        :password => opts[:password],
        :port     => opts[:port]
      ) do |session|
        ready = true
        loop {
          break if self.shutdown?
          self.process(session)
          session.loop
          sleep 0.01
        }
      end
    rescue
      puts "Failed while running ssh session! See $ssh_error for

the exception."
$ssh_error = $!
ensure
ready = true
end
}
sleep 0 until ready
end

def shutdown?
  @shutdown
end

def shutdown
  @shutdown = true
end

def execute(&blk)
  raise "Session shutdown" if shutdown?
  @queue << blk
  nil
end

def process(session)
  while proc = @queue.pop
    proc.call(session)
  end
end

def forward_local(port, host, aux_port = port)
  execute {|session|
    session.forward.local('0.0.0.0', port, host, aux_port)
  }
end
alias outgoing forward_local

def forward_remote(port, host, aux_port = port)
  execute {|session|
    session.forward.remote_to(port, host, aux_port)
  }
end

def shell
  require 'termios'
  puts "Note: You will need to interrupt 'sleep' when your shell

is done (usually ^C)."
execute {|session|
stdin_buffer = lambda do |enable|
attrs = Termios::getattr($stdin)
if enable
attrs.c_lflag |= Termios::ICANON | Termios::ECHO
else
attrs.c_lflag &= ~(Termios::ICANON | Termios::ECHO)
end
Termios::setattr($stdin, Termios::TCSANOW, attrs)
end

    begin
      stdin_buffer[false]

      shell = session.shell.open(:pty => true)

      loop do
        break unless shell.open?
        if IO.select([$stdin],nil,nil,0.01)
          data = $stdin.sysread(1)
          shell.send_data data
        end

        $stdout.print shell.stdout while shell.stdout?
        $stdout.flush
      end
    ensure
      stdin_buffer[true]
    end
  }
  sleep
end
alias incoming forward_remote

end

Object.const_set(‘DynamicSSHSession’, dynamic_session_class) unless
Object.constants.include? ‘DynamicSSHSession’

dynamic_session_class.new(opts)
rescue
puts “Failed to create an ssh session! See $ssh_error for the
exception.”
$ssh_error = $!
end
private :ssh_session

Like haskell’s sequence. Really nice to have but recursive.

I should change this it an iterative solution sometime.

Recursion is usually not a problem for realistic inputs.

class Array
def sequence(i = 0, *a)
return [a] if i == size
self[i].map {|x|
sequence(i+1, *(a + [x]))
}.inject([]) {|m, x| m + x}
end
end

class Symbol
def to_proc
lambda {|*args| args.shift.send(self, *args)}
end
end

Modulized blank slate. Only removes current not future

methods for simplicities sake.

module Blank
def self.append_features(base)
base.module_eval {
instance_methods.each {|m| undef_method m unless m =~ /^__/}
}
end
end

This is mostly a toy but it has been useful in a few cases

where I needed to slowly build up a proc inside multiple

calls

class It < Proc
instance_methods.each {|m| undef_method m unless m =~ /^__/}

def method_missing(*args, &blk)
It.new {|x|
Proc.instance_method(:call).bind(self).call(x).send(*args, &blk)}
end
end

def it
if block_given?
It.new
else
It.new {|x| x}
end
end
private :it

That is about half of it. I’ve got more stuff like gray number stuf,
unbound method extensions, and some new meta-programming stuff but it
all needs a little more work first. I should also note that I wrap my
irbrc file with a begin rescue end. The rescue just prints the
presence of an error and then shoves $! into $irbrc_error. This is
nice for occasions when you might be trying out new 1.9 builds or use
rails (they don’t correctly initialize IRB so it causes failed loads
of irbrc – keeps the output a little cleaner).

I will probably do another clean-up before RubyConf so we can all
share .irbrc’s ;-). I’ll probably end up removing more things then I
add (i.e. I really don’t use Symbol#to_proc that much).

One last thing, I was wondering if anyone would be interested in a
series of gems that act as automatic irb plugins? it might be fun to
gemify some of these things.

Brian.

Ross B. wrote:

   if instance_methods(false).include? meth.to_s
     puts `ri #{self}##{meth}`
   else
     super
   end
 else
   puts `ri #{self}`
 end

end
end

I think that came out of my .irbrc, but it’s always missed one thing:
a nice notation for class methods:

irb(main):014:0> IO.ri “close”
--------------------------------------------------------------- IO#close
ios.close => nil

irb(main):015:0> IO.ri “open”
More than one method matched your request. You can refine
your search by asking for information on one of:

Of course you can always do this:

irb(main):016:0> ri “IO.open”
--------------------------------------------------------------- IO::open
IO.open(fd, mode_string=“r” ) => io
IO.open(fd, mode_string=“r” ) {|io| block } => obj

@everyone - that is a great dump ideas. Very cool. (sorry for not
replying earlier - Ruby Forum’s email notifier seemed to have been
playing up).

Re: RubyConf - It’d be great to see an irb_tools gem come out of the
conference now! :slight_smile:

Nic

On 10/18/06, Dr Nic [email protected] wrote:

@everyone - that is a great dump ideas. Very cool. (sorry for not
replying earlier - Ruby Forum’s email notifier seemed to have been
playing up).

Re: RubyConf - It’d be great to see an irb_tools gem come out of the
conference now! :slight_smile:

It’s sad you mention that. Ironic too [1]. I had to cancel my trip
yesterday on request from the company I work for. I’ll definitely miss
going but I’ll avoid thinking about it to avoid souring the rest my
week too badly. So… please take great notes!

I still want to sit down and clean up my irb stuff into plugins. Maybe
I’ll setup a Rubyforge project after crunch time has died down at
work. BUT don’t let that stop anyone from beating me to the punch.

Brian.

[1] I have been sad to see many friends cancel their trips as well
telling them I would miss their attendance.

Dr Nic wrote:

Does anyone any interesting things in their .irbrc file?

This is useful sometimes:

def dump_history(file=nil)
if file
File.open(file, “w”) do |f|
f.puts IRB::ReadlineInputMethod::HISTORY.to_a
end
else
puts IRB::ReadlineInputMethod::HISTORY.to_a
end
end

And there is this gem from Logan C.:

def reset_irb
exec($0)
end

I’ve been using this guy for code that prints copious output to the
terminal. I’m sure it could be improved a bit, but I’ve found it
useful.

def less
require ‘stringio’
$stdout, sout = StringIO.new, $stdout
yield
$stdout, str_io = sout, $stdout
IO.popen(‘less’, ‘w’) do |f|
f.write str_io.string
f.flush
f.close_write
end
end

I tend to use that in conjunction with yaml dumps to look at complex
data structures, rather than pp, but that would work just as well.

def yp(*data)
require ‘yaml’
puts YAML::dump(*data)
end

Give them a whirl like so:

$ irb
less { yp IRB.conf }

Brian M. wrote:

On 10/18/06, Dr Nic [email protected] wrote:

@everyone - that is a great dump ideas. Very cool. (sorry for not
replying earlier - Ruby Forum’s email notifier seemed to have been
playing up).

Re: RubyConf - It’d be great to see an irb_tools gem come out of the
conference now! :slight_smile:

It’s sad you mention that. Ironic too [1]. I had to cancel my trip
yesterday on request from the company I work for. I’ll definitely miss
going but I’ll avoid thinking about it to avoid souring the rest my
week too badly. So… please take great notes!

I misconstrude my attendence - I’m not able to go. Went to Railsconf,
wife said “that will be sufficient for you for the year” (we’re in
Europe). Bummer. But she’s excited about Railsconf2007 - she wants to go
on holidays in California :slight_smile:

I still want to sit down and clean up my irb stuff into plugins. Maybe
I’ll setup a Rubyforge project after crunch time has died down at
work. BUT don’t let that stop anyone from beating me to the punch.

Remember to use newgem scaffolding for all your new gem generation needs
:slight_smile:

http://drnicwilliams.com/2006/10/11/generating-new-gems/

Nic