6

Is there an easy way to repeat a previous command in Ruby irb? I wish to have something like using exclamation mark (!) in Unix.

Thank you.

Robert A Henru
  • 2,222
  • 4
  • 21
  • 25

8 Answers8

11
def repeat_last_irb
  eval(IRB.CurrentContext.io.line(-2))
end

then you can use replat_last_irb in you irb console to run last input.

IRB.CurrentContext.io is like this below:

ruby-1.9.3-p0 :001 > def hello
ruby-1.9.3-p0 :002?>   end
 => nil 
ruby-1.9.3-p0 :003 > IRB.CurrentContext.io
 => #<IRB::ReadlineInputMethod:0x00000001c7b860 @file_name="(line)", @line_no=3, @line=[nil, "def hello\n", "end\n", "IRB.CurrentContext.io\n"], @eof=false, @stdin=#<IO:fd 0>, @stdout=#<IO:fd 1>, @prompt="ruby-1.9.3-p0 :003 > "> 

this Object save irb all io info, and with a line method to get every line you input.

so, we can use eval to repeat last input.

Hooopo
  • 1,380
  • 10
  • 16
  • Hi, rather than using offset, I found that we can put the line number that we want to repeat.. thanks! with additional method I can do it easily! – Robert A Henru Jun 01 '12 at 23:43
8

Up arrow gets you history line by line. Pry has more goodies but I haven't tried it yet.

seph
  • 6,066
  • 3
  • 21
  • 19
  • Ctrl-r will also reverse search through the history, in both IRB and Pry (I assume it's a general readline feature). – d11wtq Jun 01 '12 at 12:16
  • @d11wtq - I'm getting ctrl-r in 1.8.7 but not 1.9.3 - did we lose it? Or is my irb broken? – seph Jun 01 '12 at 12:42
  • I suspect it has been compiled against a different version of readline. Works fine for me. – d11wtq Jun 01 '12 at 12:44
  • @d11wtq - Thanks. I will have to see if I can get that back. – seph Jun 01 '12 at 12:47
  • 2
    @ d11wtq - Found the answer here in case any one is interested(osx specific): http://hints.macworld.com/article.php?story=20080313113705760 – seph Jun 01 '12 at 12:54
  • good to know, thanks. I have ruby installed on my mac, but almost always work inside a linux VM running under VMWare :) – d11wtq Jun 01 '12 at 13:58
6

Aside from pressing up arrow and enter, the Pry REPL let's you reply entire expressions (rather than just lines) using the play -i command:

see here:

[31] (pry) main: 0> (1..5).map do |v|
[31] (pry) main: 0*   v * 2
[31] (pry) main: 0* end  
=> [2, 4, 6, 8, 10]
[32] (pry) main: 0> play -i 31
=> [2, 4, 6, 8, 10]
[33] (pry) main: 0> 

You simply pass to play -i the expression number (the number in [] adjacent to the prompt) for the code you want to replay.

For more info on the play command see the wiki page also check out the Entering input for other tricks related to using and manipulating input history

Alternatively, if you want to just replay individual lines of history, you can first view history using the hist command and then replay it using hist --replay as follows:

[37] (pry) main: 0> puts "hello world"
hello world
=> nil
[38] (pry) main: 0> hist --tail
9699: _file_
9700: (1..10).map do |v|
9701: (1..5).map do |v|
9702:   v * 2
9703: end
9704: play -i 31
9705: _
9706: hist --tail
9707: hist -r
9708: puts "hello world"
[39] (pry) main: 0> hist --replay 9708
hello world
=> nil
[41] (pry) main: 0> 

Alternatively, if you just want to replay the last line input, and you don't want to use up arrow (for whatever reason) then simply use: hist --replay -1. As always the wiki contains more info on the hist command.

horseyguy
  • 29,455
  • 20
  • 103
  • 145
3

The quickest way to repeat (or modify) an earlier command that is more than just a couple of steps back in the history, is to search for it by typing Ctrl+R followed by some substring of the command in question.

For more keyboard shortcuts provided by the GNU Readline library, look here. They are supported by many shells and other applications as well.

Lars Haugseth
  • 14,721
  • 2
  • 45
  • 49
  • It would be nice, but Ctrl-R isn't supported in `irb`. – kfb Jun 01 '12 at 11:58
  • 2
    @r_ that is not true. IRB supports Ctrl-R just fine for me (ruby 1.9.3). I think it's actually a readline feature, so probably depends on your version of libreadline. – d11wtq Jun 01 '12 at 12:19
  • It's been in libreadline for many years, so I'd say it's more a matter of whether Ruby/IRB was compiled with libreadline support. It should be as long as you have libreadline installed when you install/compile Ruby/IRB. Without libreadline you probably won't be able to use arrow keys to navigate the history either. – Lars Haugseth Jun 01 '12 at 12:56
  • Ah, my mistake--I didn't have libreadline when I built Ruby, so I didn't realise I was missing this functionality! Thanks for the heads-up! – kfb Jun 01 '12 at 13:49
3

Somewhat related.

In IRB, the result of the last executed command is saved in _. You can also use that one.

Example

1.9.3p194 :001 > 2 + 2
 => 4 
1.9.3p194 :002 > _
 => 4 
1.9.3p194 :003 > _ * 3
 => 12 
1.9.3p194 :004 > _
 => 12 

This proved to be very useful for me, especially in rails console.

shime
  • 8,746
  • 1
  • 30
  • 51
2

I don't think there's any kind of numbered history support (such as like gdb), but you can use the arrow keys to navigate through history, the same as you can in the shell.

Update

Turns out I'm completely wrong, and Hooopo is right; you can access the history via the IRB.CurrentContext.io.line method, so

eval IRB.CurrentContext.io.line <line number>

will repeat the command. As Hooopo also says, wrapping this in a method works correctly:

def r(number)
  eval IRB.CurrentContext.io.line number
end

then

ruby-1.9.3-p0 :004 > puts "hello"
hello
 => nil 
ruby-1.9.3-p0 :005 > r 004 # (or 'r 4')
hello
 => nil 
kfb
  • 6,252
  • 6
  • 40
  • 51
1

The irb REPL doesn't natively support history expansion, which is what you seem to be looking for. For a solid alternative, the pry REPL offers the replay command.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199
0

You can also backtrace commands in irb by starting it with

irb --tracer

Now the up arrow will go back thru the irb commands. (Using Ruby 2.3.3)

Kenneth Wagner
  • 111
  • 1
  • 6