-.- --. .-. --..

Pry's edit command in semi-detail

07 Feb 2014

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 class First
2   def first
3     "First"
4   end
5 end
6 
7 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 File.open("/usr/var/tmp/text.txt", "w") { |f| f.write(`cat first.txt`) }
2 cat: first.txt: No such file or directory
3 => 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.