summaryrefslogtreecommitdiff
path: root/README.markdown
blob: b0f9ec2d025992bd1dbabd648e98a881c5c85fb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
Pry
=============

(C) John Mair (banisterfiend) 2010

_attach an irb-like session to any object at runtime_

Pry is a simple Ruby REPL (Read-Eval-Print-Loop) that specializes in the interactive
manipulation of objects during the running of a program.

It is not based on the IRB codebase and is small, at around 260 LOC.

* Install the [gem](https://rubygems.org/gems/pry): `gem install pry`
* Read the [documentation](http://rdoc.info/github/banister/pry/master/file/README.markdown)
* See the [source code](http://github.com/banister/pry)

example: Interacting with an object at runtime 
---------------------------------------

With the `Pry.start()` method we can pry (open an irb-like session) on
an object. In the example below we open a Pry session for the `Test` class and execute a method and add
an instance variable. The current thread is halted for the duration of the session.

    require 'pry'
    
    class Test
      def self.hello() "hello world" end
    end

    Pry.start(Test)

    # Pry session begins on stdin
    Beginning Pry session for Test
    pry(Test)> self
    => Test
    pry(Test)> hello
    => "hello world"
    pry(Test)> @y = 20
    => 20
    pry(Test)> exit
    Ending Pry session for Test

    # program resumes here

If we now inspect the `Test` object we can see our changes have had
effect:

    Test.instance_variable_get(:@y) #=> 20

#### Alternative Syntax

You can also use the `obj.pry` or `pry(obj)` syntax to start a pry session on
`obj`. e.g

    5.pry
    Beginning Pry session for 5
    pry(5)>

OR

    pry 6
    beginning Pry session for 6
    pry(6)>
    
example: Pry sessions can nest arbitrarily deep so we can pry on objects inside objects:
----------------------------------------------------------------------------------------

Here we will begin Pry at top-level, then pry on a class and then on
an instance variable inside that class:

    # Pry.start() without parameters begins a Pry session on top-level (main)
    Pry.start
    Beginning Pry session for main
    pry(main)> class Hello
    pry(main)*   @x = 20
    pry(main)* end
    => 20
    pry(main)> Pry.start Hello
    Beginning Pry session for Hello
    pry(Hello):1> instance_variables
    => [:@x]
    pry(Hello):1> Pry.start @x
    Beginning Pry session for 20
    pry(20:2)> self + 10
    => 30
    pry(20:2)> exit
    Ending Pry session for 20
    pry(Hello):1> exit
    Ending Pry session for Hello
    pry(main)> exit
    Ending Pry session for main

The number after the `:` in the pry prompt indicates the nesting
level. To display more information about nesting, use the `nesting`
command. E.g

    pry("friend":3)> nesting
    Nesting status:
    0. main (Pry top level)
    1. Hello
    2. 100
    3. "friend"
    => nil
    
We can then jump back to any of the previous nesting levels by using
the `jump_to` command:

    pry("friend":3)> jump_to 1
    Ending Pry session for "friend"
    Ending Pry session for 100
    => 100
    pry(Hello):1>

If we just want to go back one level of nesting we can of course 
use the `quit` or `exit` or `back` commands.

To break out of all levels of Pry nesting and return immediately to the
calling process use `exit_all`:

    pry("friend":3)> exit_all
    Ending Pry session for "friend"
    Ending Pry session for 100
    Ending Pry session for Hello
    Ending Pry session for main
    => main
    
    # program resumes here

Features and limitations
------------------------

Pry is an irb-like clone with an emphasis on interactively examining
and manipulating objects during the running of a program.

Its primary utility is probably in debugging, though it may have other
uses (such as implementing a quake-like console for games, for example). Here is a
list of Pry's features along with some of its limitations given at the
end.

Features:

* Pry can be invoked at any time and on any object in the running program.
* Pry sessions can nest arbitrarily deeply -- to go back one level of nesting type 'exit' or 'quit' or 'back'
* Use `_` to recover last result.
* Pry has multi-line support built in.
* Pry gives good control over nested sessions (important when exploring complicated runtime state)
* Pry is not based on the IRB codebase.
* Pry is small; around 260 LOC.
* Pry implements all the methods in the REPL chain separately: `Pry.r`
for reading; `Pry.re` for eval; `Pry.rep` for printing; and `Pry.repl`
for the loop (`Pry.start` is simply an alias for `Pry.repl`). You can
invoke any of these methods directly depending on exactly what aspect of the functionality you need.

Limitations:

* Pry does not pretend to be a replacement for `irb`,
  and so does not have an executable. It is designed to be used by
  other programs, not on its own. For a full-featured `irb` replacement
  see [ripl](https://github.com/cldwalker/ripl)
* Although Pry works fine in Ruby 1.9, only Ruby 1.8 syntax is
  supported. This is because Pry uses the
  [RubyParser](https://github.com/seattlerb/ruby_parser)
  gem internally to  validate expressions, and RubyParser, as yet, only parses Ruby 1.8
  code. In practice this usually just means you cannot use the new
  hash literal syntax (this: syntax) or the 'stabby lambda' syntax
  (->).
 
Commands
-----------

### The Pry API:

* `Pry.start()` and `Pry.into()` and `Pry.repl()` are all aliases of
oneanother. They all start a Read-Eval-Print-Loop on the object they
receive as a parameter. In the case of no parameter they operate on
top-level (main). They can receive any object or a `Binding`
object as parameter.
* `obj.pry` and `pry(obj)` may also be used as alternative syntax to `Pry.start(obj)`
* If, for some reason you do not want to 'loop' then use `Pry.rep()`; it
only performs the Read-Eval-Print section of the REPL - it ends the
session after just one line of input. It takes the same parameters as
`Pry.repl()`
* Likewise `Pry.re()` only performs the Read-Eval section of the REPL,
it returns the result of the evaluation or an Exception object in
case of error. It also takes the same parameters as `Pry.repl()`
* Similarly `Pry.r()` only performs the Read section of the REPL, only
returning the Ruby expression (as a string). It takes the same parameters as all the others.

### Session commands

Pry supports a few commands inside the session itself. These commands are
not methods and must start at the beginning of a line, with no
whitespace in between.

If you want to access a method of the same name, prefix the invocation by whitespace.

* Typing `!` on a line by itself will refresh the REPL - useful for
  getting you out of a situation if the parsing process
  goes wrong.
* `status` shows status information about the current session.
* `help` shows the list of session commands with brief explanations.
* `exit` or `quit` or `back` will end the current Pry session and go
  back to the calling process or back one level of nesting (if there
  are nested sessions).
* `exit_program` or `quit_program` will end the currently running
  program.
* `nesting` shows Pry nesting information.
* `jump_to <nest_level>`  unwinds the Pry stack (nesting level) until the appropriate nesting level is reached
  -- as per the output of `nesting`
* `exit_all` breaks out of all Pry nesting levels and returns to the
  calling process.
* You can type `Pry.start(obj)` or `obj.pry` to nest another Pry session within the
  current one with `obj` as the receiver of the new session. Very useful
  when exploring large or complicated runtime state.

Contact
-------

Problems or questions contact me at [github](http://github.com/banister)