Irb History Itches Eliminated
Irb, ruby’s interactive shell, is awesome for interactive programming. You can write a few lines and test out that language feature you weren’t aware of. However as your testing becomes more elaborate it can become annoying to rewrite your code. So how do you retrieve old code? Your history, of course.
When I read programming articles, I like to find the final source code so I don’t copy and paste several times. I’m laaaayzy like that. Update: The newer and improved version of the code we’re going to talk about is here.
From the ruby garden I found out where my history was stored, Readline::HISTORY
. Wanting to make command history access as intuitive as possible, I wanted to pull up commands by the command numbers seen in irb’s prompt. Noticing that Readline::HISTORY
starts out with previous history, I saved its original size for later use. To pull up commands inclusively between two numbers I did the following:
$original_history_size = Readline::HISTORY.size
def history_list(first_num,second_num=Readline::HISTORY.size - 1)
Readline::HISTORY.to_a[(first_num + $original_history_size - 1) .. (second_num +
$original_history_size - 1) ]
end
And what if wanted to print these out in a more readable format or eval some of the lines to bring back the code to a previous state?
def print_history(*args)
puts history_list(*args).join("\n")
end
def eval_history(*args)
eval %[ #{history_list(*args).join("\n")} ]
end
Now, what if I wanted to only eval certain lines of the code say lines 1,4,8-12,15. Well I wrote a brief Array
method, multislice
, that literally would take the previous string ‘1,4,8-12,15’ and return back the 1st,4th,8th-12th and 15th elements of an array. With multislice
I wrote a method similar to history_list
.
As I wrote these methods I wondered if I’d satisified all my itches for a more rapid irb programming environment. Wellll, all except one: editing already entered irb code, without the hassle of consciously pasting code and naming a temporary file. So naturally I used an automatically generated tempfile using tempfile.rb. First I wrote a method to edit a string:
def edit(string=nil,editor=ENV['EDITOR'])
editor ||= raise "editor must be given or defined by EDITOR environment variable"
tempfile = Tempfile.new('edit')
File.open(tempfile.path,'w') {|f| f.write(string) } if string
system("#{editor} #{tempfile.path}")
File.open(tempfile.path) {|f| f.read }
end
And then another to edit specified commands:
def edit_history(*args)
history_string = history_list_or_slice(*args).join("\n")
edit(history_string)
end
So for now my irb itches are satisfied. Are yours?