Thoughts on rewriting irb?

Hi,
  I wrote up a post on a mini irb which does better irb completion,
persistent history and error handling in 7 lines:
http://tagaholic.me/2009/07/23/mini-irb-and-mini-script-console.html

If you're curious the code looks like this:
%w{readline rubygems bond bond/completion}.each {|e| require e }
history_file = File.join(ENV["HOME"], '.mini_irb_history')
IO.readlines(history_file).each {|e| Readline::HISTORY << e.chomp } if
File.exists?(history_file)
while (input = Readline.readline('>> ', true)) != 'exit'
  begin puts "=> #{eval(input).inspect}"; rescue Exception; puts
"Error: #{$!}" end
end
File.open(history_file, 'w') {|f| f.write Readline::HISTORY.to_a.join
("\n") }

Since that probably came out horribly, you could also just see this
snippet: http://gist.github.com/68608

At first, it may seem like a joke to compare it to irb but imho it
does the brunt of what a repl should do. All of irb's features:
workspaces, jobs, config options, command framework are features which
the majority of ruby programmers don't seem to use. Personally the
only thing I'd port to mini-irb is a ruby lexer to detect multiple
lines of ruby. So what are other people's two cents? If you could
rewrite irb, what features would you give it?

ghorner wrote:

  begin puts "=> #{eval(input).inspect}"; rescue Exception; puts

Do you want

eval(input, b)

where b is a Binding that was constructed before the loop? Otherwise, how will this support local vars?

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Hi,

  I wrote up a post on a mini irb which does better irb completion,
persistent history and error handling in 7 lines:
Tagaholic - Mini Irb and Mini Script/Console

If you're curious the code looks like this:
[...]

I'm very disappointed about Irb. The thing I miss most is some way
to say "Examine the object now" while debugging. To be honest I
wrote me my own interactive Ruby and I didn't use Irb for about a
year. I would like to publish my one but the thing leaving me
dissatified is the Readline library. A real good command line
library would allow me to do things like entering my favourite
editor, be able to yield coloured output at the prompt and maybe
the entered line, a configurable history management, and much
more. The objects environment sould be left untouched; for example
the "exit" method shouldn't be redefined, rather something like
the PostgreSQL \q command should replace it.

I would like to share my approach for further development.

Bertram

···

Am Freitag, 24. Jul 2009, 03:50:06 +0900 schrieb ghorner:

--
Bertram Scharpf
Stuttgart, Deutschland/Germany
http://www.bertram-scharpf.de

ghorner wrote:
> begin puts "=> #{eval(input).inspect}"; rescue Exception; puts

Do you want

eval(input, b)

where b is a Binding that was constructed before the loop? Otherwise,
how will this support local vars?

Joel,
  not sure I follow. In mini-irb this works:

  >> b = 2
  => 2
  >> 'b' * b
  => "bb"

As does placing local variables before the loop being picked up by
eval. Could you elaborate?
Gabriel

···

On Jul 23, 9:47 pm, Joel VanderWerf <vj...@path.berkeley.edu> wrote:

I'm very disappointed about Irb. The thing I miss most is some way
to say "Examine the object now" while debugging. To be honest I

Ditto on the disappointment. You can use breakpoint for examining an
object at any point of your program.

dissatified is the Readline library. A real good command line
library would allow me to do things like entering my favourite
editor, be able to yield coloured output at the prompt and maybe
the entered line, a configurable history management, and much

Can't you enter what you need to via "system 'myeditor'"? Colored
output is
done ok with wirble. Readline::HISTORY can be as configurable as you
make it. Here's
my own history management module:

more. The objects environment sould be left untouched; for example
the "exit" method shouldn't be redefined, rather something like
the PostgreSQL \q command should replace it.

With the 7-liner in this post you could change 'exit' to '\q'.

I would like to share my approach for further development.

Share more if you'd like.

Gabriel

···

On Jul 24, 12:16 am, Bertram Scharpf <li...@bertram-scharpf.de> wrote:

cldwalker wrote:

ghorner wrote:

  begin puts "=> #{eval(input).inspect}"; rescue Exception; puts

Do you want

eval(input, b)

where b is a Binding that was constructed before the loop? Otherwise,
how will this support local vars?

Joel,
  not sure I follow. In mini-irb this works:

  >> b = 2
  => 2
  >> 'b' * b
  => "bb"

As does placing local variables before the loop being picked up by
eval. Could you elaborate?
Gabriel

Here's a simplified version of your code:

$ cat mirb.rb
%w{readline rubygems}.each {|e| require e }
while (input = Readline.readline('>> ', true)) != 'exit'
   begin puts "=> #{eval(input).inspect}"; rescue Exception; puts
"Error: #{$!}" end
  end
$ ruby mirb.rb
>> input
=> "input"

This is fixable using bindings:

$ cat mirb.rb
%w{readline rubygems}.each {|e| require e }
def get_binding; binding; end
b = get_binding
while (input = Readline.readline('>> ', true)) != 'exit'
   begin puts "=> #{eval(input, b).inspect}"; rescue Exception; puts
"Error: #{$!}" end
  end
$ ruby mirb.rb
>> input

>>

(Now, some might say that's still a bug, but at least it doesn't expose a local variable of mini-irb.)

···

On Jul 23, 9:47 pm, Joel VanderWerf <vj...@path.berkeley.edu> wrote:

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Thanks for pointing that out. Would you know why irb does some funkier
binding with its IRB.conf[:CONTEXT_MODE] option i.e. binding to a
temporary file? I asked about it here,
http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/6aa102dba71850f3,
but no one seemed to know.
Now with proper binding, mini-irb stands at less than 10 lines. So I'm
still asking, what of the 5000+ loc in irb do people actually use?

···

On Jul 24, 6:36 pm, Joel VanderWerf <vj...@path.berkeley.edu> wrote:

cldwalker wrote:
> On Jul 23, 9:47 pm, Joel VanderWerf <vj...@path.berkeley.edu> wrote:
>> ghorner wrote:
>>> begin puts "=> #{eval(input).inspect}"; rescue Exception; puts
>> Do you want

>> eval(input, b)

>> where b is a Binding that was constructed before the loop? Otherwise,
>> how will this support local vars?

> Joel,
> not sure I follow. In mini-irb this works:

> >> b = 2
> => 2
> >> 'b' * b
> => "bb"

> As does placing local variables before the loop being picked up by
> eval. Could you elaborate?
> Gabriel

Here's a simplified version of your code:

$ cat mirb.rb
%w{readline rubygems}.each {|e| require e }
while (input = Readline.readline('>> ', true)) != 'exit'
begin puts "=> #{eval(input).inspect}"; rescue Exception; puts
"Error: #{$!}" end
end
$ ruby mirb.rb
>> input
=> "input"

This is fixable using bindings:

$ cat mirb.rb
%w{readline rubygems}.each {|e| require e }
def get_binding; binding; end
b = get_binding
while (input = Readline.readline('>> ', true)) != 'exit'
begin puts "=> #{eval(input, b).inspect}"; rescue Exception; puts
"Error: #{$!}" end
end
$ ruby mirb.rb
>> input

>>

(Now, some might say that's still a bug, but at least it doesn't expose
a local variable of mini-irb.)