Forum: Ruby My .irbrc for console/irb

Posted by Dr Nic (nicwilliams)
on 2006-10-12 14:32
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
Posted by Farrel Lifson (Guest)
on 2006-10-12 14:59
(Received via mailing list)
On 12/10/06, Dr Nic <drnicwilliams@gmail.com> wrote:
>
>
I haven't used it but Wirble(http://pablotron.org/software/wirble/)
looks pretty cool.

Farrel
Posted by Dr Nic (nicwilliams)
on 2006-10-12 15:19
Farrel Lifson wrote:
> On 12/10/06, Dr Nic <drnicwilliams@gmail.com> wrote:
>>
>>
> I haven't used it but Wirble(http://pablotron.org/software/wirble/)
> looks pretty cool.

Very nifty indeed.
Posted by Nick Sieger (Guest)
on 2006-10-12 16:36
(Received via mailing list)
On 10/12/06, Dr Nic <drnicwilliams@gmail.com> 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://errtheblog.com/post/26
http://blog.nicksieger.com/articles/2006/04/23/tweaking-irb

Cheers,
/Nick
Posted by Rick Denatale (rdenatale)
on 2006-10-13 21:48
(Received via mailing list)
On 10/12/06, Dr Nic <drnicwilliams@gmail.com> 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/
Posted by Sophi Italy (itsme213)
on 2006-10-18 10:38
(Received via mailing list)
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,...
Posted by Brian Mitchell (Guest)
on 2006-10-18 10:38
(Received via mailing list)
On 10/12/06, Dr Nic <drnicwilliams@gmail.com> 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 ;-)
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.
Posted by Ross Bamford (Guest)
on 2006-10-18 10:38
(Received via mailing list)
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
Posted by Joel VanderWerf (Guest)
on 2006-10-18 10:39
(Received via mailing list)
Ross Bamford 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
Posted by Joel VanderWerf (Guest)
on 2006-10-18 10:39
(Received via mailing list)
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 Capaldo:

def reset_irb
   exec($0)
end
Posted by Dr Nic (nicwilliams)
on 2006-10-18 10:44
@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! :)

Nic
Posted by Brian Mitchell (Guest)
on 2006-10-18 13:01
(Received via mailing list)
On 10/18/06, Dr Nic <drnicwilliams@gmail.com> 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! :)

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.
Posted by Dr Nic (nicwilliams)
on 2006-10-18 13:05
Brian Mitchell wrote:
> On 10/18/06, Dr Nic <drnicwilliams@gmail.com> 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! :)
> 
> 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 :)

> 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 
:)

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

Nic
Posted by Lou Scoras (ljscoras)
on 2006-10-18 16:32
(Received via mailing list)
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 }
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.