Can I repeat command in irb?
Asked Answered
S

8

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.

Skeet answered 1/6, 2012 at 10:39 Comment(0)
M
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.

Maestas answered 1/6, 2012 at 10:57 Comment(1)
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!Skeet
P
8

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

Presume answered 1/6, 2012 at 10:48 Comment(6)
Ctrl-r will also reverse search through the history, in both IRB and Pry (I assume it's a general readline feature).Breuer
@Breuer - I'm getting ctrl-r in 1.8.7 but not 1.9.3 - did we lose it? Or is my irb broken?Presume
I suspect it has been compiled against a different version of readline. Works fine for me.Breuer
@Breuer - Thanks. I will have to see if I can get that back.Presume
@ d11wtq - Found the answer here in case any one is interested(osx specific): hints.macworld.com/article.php?story=20080313113705760Presume
good to know, thanks. I have ruby installed on my mac, but almost always work inside a linux VM running under VMWare :)Breuer
G
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.

Gynaecology answered 1/6, 2012 at 11:36 Comment(0)
L
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.

Lieabed answered 1/6, 2012 at 11:29 Comment(4)
It would be nice, but Ctrl-R isn't supported in irb.Nod
@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.Breuer
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.Lieabed
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!Nod
M
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.

Mier answered 1/6, 2012 at 12:36 Comment(0)
N
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 
Nod answered 1/6, 2012 at 10:49 Comment(3)
ya, I see that irb line command has an increasing number, wondering if it's useful to repeat command.Skeet
let's say I want to load this method definition automatically when starting irb, any idea how to do it?Skeet
Your r 004 will interpret 004 as an octal. Careful with that.Catholicize
K
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.

Kathyrnkati answered 1/6, 2012 at 11:5 Comment(0)
L
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)

Laurinelaurita answered 29/11, 2016 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.