My .irbrc for console/irb

D

Dr Nic

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
 
F

Farrel Lifson

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

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

Farrel
 
B

Brian Mitchell

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?

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.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.
 
B

Brian Mitchell

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?

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.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.


Funny reading through the code. I spotted a few screw-ups. Probably a
side effect of doing rapid and small changes between irb_reset's.

Brian.
 
R

Ross Bamford

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::eek:pen( 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
 
J

Joel VanderWerf

Ross said:
#### 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

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::eek:pen
Io_Open(fd, mode_string="r" ) => io
Io_Open(fd, mode_string="r" ) {|io| block } => obj
 
J

Joel VanderWerf

Dr said:
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
 
R

Rick DeNatale

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/
 
D

Dr Nic

@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
 
B

Brian Mitchell

@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.
 
D

Dr Nic

Brian said:
@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
 
L

Louis J Scoras

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 }
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top