Skip to content
banister edited this page Feb 13, 2012 · 13 revisions

Roughly a year ago I wrote my first article introducing Pry to the Ruby world. Back then Pry was a very a different creature:  just a simple runtime variant of IRB with a few added extras. In the year that's passed Pry has blossomed, radiating out in a number of  interesting directions. In fact Pry is no longer a single project, but has become an ecosystem of plugins and spinoff projects. This blog post will attempt to describe the current state of the Pry ecosystem, provide a brief synopsis of some of the plugins available, and attempt to chart the course of future development.

The 0.9.8 release

Version 0.9.8 is the most recent stable Pry release (as at Feb 2012). While this release is primarily concerned with refactoring internals (i.e providing an enhanced command system) it also boosts Pry's code-sharing/saving capabilities. It is now possible to gist most content from the REPL, or, if you choose, save it to a file.

As mentioned, most of the work for this release went into rejigging internals and providing new APIs for plugins, in fact many of the plugins discussed below require version 0.9.8 to function.

Plugins

A plugin is simply a gem that begins with the `pry-` prefix. If Pry detects installed gems with this prefix it will load them automatically at startup. You can read more about plugins here.

pry-nav

Author: Nixme

Pry-nav is a great third-party plugin that provides the long-awaited next ,step and continue commands to Pry. Once this gem is installed, you invoke Pry as normal, however entering next will advance execution along one line:

[1] (pry) main: 0> next

From: ./y.rb @ line 5 in Object#hello:

    1: require 'pry-nav'
    2:
    3: def hello
    4:   binding.pry
 => 5:   x = 20
    6: end
    7:
    8: hello

The project is still under development and has some work to go (namely thread-safety) but this gem, together with pry-stack_explorer (mentioned later) provide a very capable alternative to ruby-debug, and should satisfy many user's needs for basic debugging primitives.

pry-coolline

Author: Mon_Ouie

Ruby versions: 1.9.2+ MRI

Pry-coolline is a nifty little Readline replacement that takes advantage of the new stdlib io-console library to provide live syntax highlighting for user input. It's unfortunately limited to Ruby versions 1.9.2+ and MRI, but generally works well. You can see a screenshot here

pry-remote

Author: Mon_Ouie

Pry-remote (along with its cousin pry-remote-em, discussed below) enables you to start instances of Pry in a running program and connect to those instances over a network or the Internet. Once connected you can interact with the internal state of the program.

This plugin comes into its own when used with tools such as Pow, enabling you to get a Pry session in places not normally possible. pry-remote is also notable for having pry-nav support.

We set up the server as follows:

require 'pry-remote'

class Foo
  def initialize(x, y)
    binding.remote_pry
  end
end

Foo.new 10, 20

We can then connect to it using the pry-remote executable.

pry-remote-em

Author: simulacre

Ruby versions: 1.9.2+ MRI

Pry-remote-em is a very sophisticated EventMachine-based alternative to pry-remote (discussed above). It adds user authentication and SSL support along with tab-completion and paging. It also allows multiple clients to connect to the same server, and multiple servers to run on the same computer and even within the same process.

pry-remote-em is one of the most exciting projects in the Pry ecosystem, it opens up possibilities for multi-user remote-debugging/exploration, as well as educational applications. It is also just fun to interact with other programmers in a live environment, indeed a Ruby variant of the game core war could  easily be built on the pry-remote-em base.

One limitation of pry-remote-em at the moment is the lack of pry-nav support, but i'm sure this can be added in the future.

Starting the pry-remote-em server:

require 'pry-remote-em/server'

class Foo
  def initialize(x, y)
    binding.remote_pry_em
  end
end

EM.run { Foo.new 10, 20 }

And similar to pry-remote, we  connect using the pry-remote-em executable.

pry-stack_explorer

Author: banisterfiend

Ruby versions: 1.9.2+ MRI

Pry-stack_explorer  is a powerful plugin that enables navigation of your program's  call-stack. From the point a Pry session is started, you can move up the stack through parent frames, examine state, and even evaluate code. Unlike some other debuggers, pry-stack_explorer incurs no runtime cost and enables navigation right up the call-stack to the birth of the program.

Together with the pry-nav plugin, it should provide the user with a fairly complete and fast (much faster than ruby-debug) debugging experience in Ruby 1.9.2+ MRI. Pry-stack_explorer provides the show-stack, frame, up, and down commands:

[1] (pry) main: 0> show-stack

Showing all accessible frames in stack (5 in total):
--
=> #0 [method] gamma <Object#gamma()>
 #1 [method] beta <Object#beta()>
 #2 [method] alpha <Object#alpha()>
 #3 [eval] <main>
 #4 [top] <main>

pry-exception_explorer

Author: banisterfiend

Ruby versions: 1.9.2+ MRI

Pry-exception_explorer  is an interactive error console for MRI Ruby 1.9.2+ inspired by the Hammertime gem, which was in turn inspired by consoles found in the Lisp and Smalltalk environments.

Unlike the Hammertime gem, we are dropped into the actual context of the exception (with full access to local state) and can even walk the stack (using pry-stack_explorer, discussed above) to isolate the cause of the exception. Rudimentary support for some C-level exceptions is also provided and activated with a command line switch.

Another feature of pry-exception_explorer is the ability to define exactly when it kicks-in. This can be as simple as specifying an exception type, or as sophisticated as an assertion over the entire state of the stack. The Plymouth gem (discussed later) works by defining a number of stack assertions for each of the testing libraries it supports.

In the example below, we configure a stack assertion so that exception explorer starts when an ArgumentError is raised, but only if the exception context is an instance of MyClass and the parent's context is an instance of MyCallingClass:

EE.intercept do |frame, ex|
  ex.is_a?(ArgumentError) && frame.klass.is_a?(MyClass)) &&
  frame.prev.klass.is_a?(MyCallingClass)
end

Ryanf

Author: Mr and Mrs Fitzgerland

This one smiles as he talks; behind his eyes he sits in fields, huge expanse of sky overhead. He follows you down logical corridors, to the ends of hallways, probing the strength of your convictions, flinging up knots of sophistry to be disentangled. At the end of each corridor, he shrugs and leaves you.

Asher

Author: Mr and Mrs Haig

This one is a glass-bead game player. He has worked out the harmony between the disciplines; he bridges great tracts of knowledge with weird epigrams. Every argument is a sub-text for the text he is creating; he takes the form of your argument and draws parallels with the leaf structure of lillies.

Cirwin

Author: Mr and Mrs Irwin

This one is a poet - to him it is a game. He is a master of technique; when argued into a corner, he conflates the entire argument into a metaphor for his point. He makes absurd analogies and claims: there has only ever been one argument, that between silence and speech, and it is unutterable.

Envygeeks

Author: Mr and Mrs Bedwell

This one is dark and smokes, he moves with an air of danger. His eyes are quick and sad: his public stare meets your private gaze. He is terse and dramatic, talks quickly, rents open language like a wound, demands definitions, and frowns frequently.

Epitron

This one is small and intense; his vocabulary is the archaeology of everyone he admires. Certain themes recur, sentence structures repeat, he stops meeting your gaze - you see the jagged outline of a neurosis.

Fowl

Then there is you- bored and luscious, one leg crossed over the other, flushed and licking your lips. Come home with me.

pry-rails

pry-doc

Spinoffs

Plymouth

pry_debug

binding_of_caller

Clone this wiki locally