Today, I came across a neat feature of Pry’s edit command and thought I’d prepare a write-up detailing the power of the edit
command in Pry. If you’re unfamiliar with the tool Pry, you should get started and here’s a great article.
Inside Pry, you can call the edit
command which will create a temporary file and open it up in the configured text editor. And it’s power is not limited to that feature alone.
When you run edit
inside a pry window, it opens up a temporary file for editing. The default contents of this file will be the last command run. The editor of choice can be configured in the ~/.pryrc
with the directive Pry.config.editor = 'vim'
. Once you save the file and close it, it gets run by the pry session and you can access whatever elements you define inside of it. This simple command packs a lot of features that you might find helpful in prototyping a piece of logic quickly.
With a filename as argument
The edit
command can be invoked with a filename as an argument which will open a editor session with the file name (and path) that you supplied. Open up a Pry session in the terminal and run the following command:
edit first.rb
This should open up a file in the directory you’ve started the Pry session with the name <directory in which pry is run>/first.rb
.
Add the following code to this file:
1
2
3
4
5
6
7
class First
def first
"First"
end
end
First.new.first
When you hit Ctrl+s
(or what ever that is you do to save the file) and close it, the contents should get eval-ed in the Pry session and you should see the following output:
"First"
This file can be reopened by running edit first.rb
again inside the pry session.
Edit without arguments
The edit
command can also be used without passing any arguments which will open a tempfile with the contents of the previously run command. This is pretty nifty if the previously run command is big and you don’t want to type the whole thing again. A contrived example:
1
2
3
File.open("/usr/var/tmp/text.txt", "w") { |f| f.write(`cat first.txt`) }
cat: first.txt: No such file or directory
=> 0
I realize I made a mistake with the file extension of the file first
. It should have been .rb
instead of .txt
but I don’t want to type the whole line again. You can argue that this can be corrected by hitting the up arrow on the keyboard which will load the previous command. That is true. I want you to forget that the up arrow exists on the keyboard for sometime. Now, the edit
command comes in handy.
Alternatively, if an switch of -t
is passed to the edit
command, it will open a blank file instead of loading the last executed command.
Edit previous input range
One killer and useful feature when debugging a script or prototyping one is the ability to go back to a definition, modify it and re-run it. This can be achieved with the -i
flag to the edit
command.
Running edit --help
gives out this information:
Usage: edit [--no-reload|--reload|--patch] [--line LINE] [--temp|--ex|FILE[:LINE]|OBJECT|--in N]
Open a text editor. When no FILE is given, edits the pry input buffer.
When a method/module/command is given, the code is opened in an editor.
Ensure `Pry.config.editor` is set to your editor of choice.
edit sample.rb edit -p MyClass#my_method
edit sample.rb --line 105 edit MyClass
edit MyClass#my_method edit --ex
edit --method edit --ex -p
https://github.com/pry/pry/wiki/Editor-integration#wiki-Edit_command
-e, --ex Open the file that raised the most recent exception (_ex_.file)
-i, --in Open a temporary file containing the Nth input expression. N may be a range
-t, --temp Open an empty temporary file
-l, --line Jump to this line in the opened file
-n, --no-reload Don't automatically reload the edited code
-c, --current Open the current __FILE__ and at __LINE__ (as returned by `whereami`)
-r, --reload Reload the edited code immediately (default for ruby files)
-p, --patch Instead of editing the object's file, try to edit in a tempfile and apply as a monkey patch
-m, --method Explicitly edit the _current_ method (when inside a method context).
-h, --help Show this message.
The --in N
flag opens a temporary file containing the Nth input expression. This also accepts a range of inputs. For example:
❯ pry -f
[1] pry(main)> puts 'Hi'
Hi
=> nil
[2] pry(main)> puts 'Hello'
Hello
=> nil
[3] pry(main)> puts 'How are you'
How are you
=> nil
[4] pry(main)> edit -t
I was written inside a tempfile created by the edit command
=> nil
[5] pry(main)> puts 'Okay, now what'
Okay, now what
=> nil
[6] pry(main)> edit -i 4
I was written inside a tempfile created by the edit command and now, I've been edited
=> nil
[7] pry(main)> edit -i 4..5
I was written inside a tempfile but now I've been edited once already
Okay, now what
=> nil
[8] pry(main)>
On the 4th line, the command opens up a vim editor window and I puts
the printed out string.
On the 7th command, a range was supplied. The opened file will contain the 4th input, which is the file with the contents "I was written inside a tempfile created by the edit command"
and the 5th line which is the command puts 'Okay, now what'
. Try it out on your own to get a better understanding.
These features form a really powerful set of tools for debugging Ruby code. Hopefully, you find them as useful as I find them to be.