mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Ripper for 1.9, RubyParser for 1.8. Fixed 1.8 inspect difficulties, added help for new commands, using method_source gem, updated README
This commit is contained in:
parent
a31d9e31c1
commit
c6ee635460
5 changed files with 62 additions and 52 deletions
|
@ -8,13 +8,14 @@ _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
|
Pry is a simple Ruby REPL (Read-Eval-Print-Loop) that specializes in the interactive
|
||||||
manipulation of objects during the running of a program.
|
manipulation of objects during the running of a program.
|
||||||
|
|
||||||
It is not based on the IRB codebase and is small, at around 260 LOC.
|
It is not based on the IRB codebase, and implements some unique REPL
|
||||||
|
commands such as `show_method` and `jump_to`
|
||||||
|
|
||||||
* Install the [gem](https://rubygems.org/gems/pry): `gem install pry`
|
* Install the [gem](https://rubygems.org/gems/pry): `gem install pry`
|
||||||
* Read the [documentation](http://rdoc.info/github/banister/pry/master/file/README.markdown)
|
* Read the [documentation](http://rdoc.info/github/banister/pry/master/file/README.markdown)
|
||||||
* See the [source code](http://github.com/banister/pry)
|
* See the [source code](http://github.com/banister/pry)
|
||||||
|
|
||||||
example: Interacting with an object at runtime
|
Example: Interacting with an object at runtime
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
With the `Pry.start()` method we can pry (open an irb-like session) on
|
With the `Pry.start()` method we can pry (open an irb-like session) on
|
||||||
|
@ -62,7 +63,7 @@ OR
|
||||||
beginning Pry session for 6
|
beginning Pry session for 6
|
||||||
pry(6)>
|
pry(6)>
|
||||||
|
|
||||||
example: Pry sessions can nest arbitrarily deep so we can pry on objects inside objects:
|
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
|
Here we will begin Pry at top-level, then pry on a class and then on
|
||||||
|
@ -137,7 +138,7 @@ uses (such as implementing a quake-like console for games, for example). Here is
|
||||||
list of Pry's features along with some of its limitations given at the
|
list of Pry's features along with some of its limitations given at the
|
||||||
end.
|
end.
|
||||||
|
|
||||||
Features:
|
####Features:
|
||||||
|
|
||||||
* Pry can be invoked at any time and on any object in the running program.
|
* 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'
|
* Pry sessions can nest arbitrarily deeply -- to go back one level of nesting type 'exit' or 'quit' or 'back'
|
||||||
|
@ -145,45 +146,40 @@ Features:
|
||||||
* Pry has multi-line support built in.
|
* Pry has multi-line support built in.
|
||||||
* Pry gives good control over nested sessions (important when exploring complicated runtime state)
|
* Pry gives good control over nested sessions (important when exploring complicated runtime state)
|
||||||
* Pry is not based on the IRB codebase.
|
* Pry is not based on the IRB codebase.
|
||||||
* Pry is small; around 260 LOC.
|
* Pry uses [RubyParser](https://github.com/seattlerb/ruby_parser) to
|
||||||
* Pry implements all the methods in the REPL chain separately: `Pry.r`
|
validate expressions in 1.8, and [Ripper](http://rdoc.info/docs/ruby-core/1.9.2/Ripper) for 1.9.
|
||||||
for reading; `Pry.re` for eval; `Pry.rep` for printing; and `Pry.repl`
|
* Pry implements all the methods in the REPL chain separately: `Pry#r`
|
||||||
for the loop (`Pry.start` is simply an alias for `Pry.repl`). You can
|
for reading; `Pry#re` for eval; `Pry#rep` for printing; and `Pry#repl`
|
||||||
|
for the loop (`Pry.start` simply wraps `Pry.new.repl`). You can
|
||||||
invoke any of these methods directly depending on exactly what aspect of the functionality you need.
|
invoke any of these methods directly depending on exactly what aspect of the functionality you need.
|
||||||
|
|
||||||
Limitations:
|
####Limitations:
|
||||||
|
|
||||||
* Pry does not pretend to be a replacement for `irb`,
|
* Pry does not pretend to be a replacement for `irb`,
|
||||||
and so does not have an executable. It is designed to be used by
|
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
|
other programs, not on its own. For a full-featured `irb` replacement
|
||||||
see [ripl](https://github.com/cldwalker/ripl)
|
see [ripl](https://github.com/cldwalker/ripl)
|
||||||
* Although Pry works fine in Ruby 1.9, only Ruby 1.8 syntax is
|
* Pry's `show_method` and `show_instance_method` commands do not work
|
||||||
supported. This is because Pry uses the
|
in Ruby 1.8.
|
||||||
[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
|
Commands
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
### The Pry API:
|
### The Pry API:
|
||||||
|
|
||||||
* `Pry.start()` and `Pry.into()` and `Pry.repl()` are all aliases of
|
* `Pry.start()` Starts a Read-Eval-Print-Loop on the object it
|
||||||
oneanother. They all start a Read-Eval-Print-Loop on the object they
|
receives as a parameter. In the case of no parameter it operates on
|
||||||
receive as a parameter. In the case of no parameter they operate on
|
top-level (main). It can receive any object or a `Binding`
|
||||||
top-level (main). They can receive any object or a `Binding`
|
object as parameter. `Pry.start()` is implemented as `Pry.new.repl()`
|
||||||
object as parameter.
|
|
||||||
* `obj.pry` and `pry(obj)` may also be used as alternative syntax to `Pry.start(obj)`
|
* `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
|
* If, for some reason you do not want to 'loop' then use `Pry.new.rep()`; it
|
||||||
only performs the Read-Eval-Print section of the REPL - it ends the
|
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
|
session after just one line of input. It takes the same parameters as
|
||||||
`Pry.repl()`
|
`Pry#repl()`
|
||||||
* Likewise `Pry.re()` only performs the Read-Eval section of the 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
|
it returns the result of the evaluation or an Exception object in
|
||||||
case of error. It also takes the same parameters as `Pry.repl()`
|
case of error. It also takes the same parameters as `Pry#repl()`
|
||||||
* Similarly `Pry.r()` only performs the Read section of the REPL, only
|
* 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.
|
returning the Ruby expression (as a string). It takes the same parameters as all the others.
|
||||||
|
|
||||||
### Session commands
|
### Session commands
|
||||||
|
@ -202,6 +198,13 @@ If you want to access a method of the same name, prefix the invocation by whites
|
||||||
* `exit` or `quit` or `back` will end the current Pry session and go
|
* `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
|
back to the calling process or back one level of nesting (if there
|
||||||
are nested sessions).
|
are nested sessions).
|
||||||
|
* `ls` returns a list of local variables and instance variables in the
|
||||||
|
current scope
|
||||||
|
* `cd <var>` starts a `Pry` session on the variable <var>. E.g `cd @x`
|
||||||
|
* `show_method <methname>` Displays the sourcecode for the method
|
||||||
|
<methname>. E.g `show_method hello`
|
||||||
|
* `show_instance_method <methname>` Displays the sourcecode for the
|
||||||
|
instance method <methname>. E.g `show_instance_method goodbye`
|
||||||
* `exit_program` or `quit_program` will end the currently running
|
* `exit_program` or `quit_program` will end the currently running
|
||||||
program.
|
program.
|
||||||
* `nesting` shows Pry nesting information.
|
* `nesting` shows Pry nesting information.
|
||||||
|
|
3
Rakefile
3
Rakefile
|
@ -7,7 +7,7 @@ require "#{direc}/lib/pry/version"
|
||||||
|
|
||||||
CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
|
CLOBBER.include("**/*.#{dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
|
||||||
CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
CLEAN.include("ext/**/*.#{dlext}", "ext/**/*.log", "ext/**/*.o",
|
||||||
"ext/**/*~", "ext/**/*#*", "ext/**/*.obj",
|
"ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "**/*#*", "**/*#*.*",
|
||||||
"ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake")
|
"ext/**/*.def", "ext/**/*.pdb", "**/*_flymake*.*", "**/*_flymake")
|
||||||
|
|
||||||
def apply_spec_defaults(s)
|
def apply_spec_defaults(s)
|
||||||
|
@ -20,6 +20,7 @@ def apply_spec_defaults(s)
|
||||||
s.description = s.summary
|
s.description = s.summary
|
||||||
s.require_path = 'lib'
|
s.require_path = 'lib'
|
||||||
s.add_dependency("ruby_parser",">=2.0.5")
|
s.add_dependency("ruby_parser",">=2.0.5")
|
||||||
|
s.add_dependency("method_source",">=0.1.4")
|
||||||
s.homepage = "http://banisterfiend.wordpress.com"
|
s.homepage = "http://banisterfiend.wordpress.com"
|
||||||
s.has_rdoc = 'yard'
|
s.has_rdoc = 'yard'
|
||||||
s.files = Dir["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "lib/**/*.rb",
|
s.files = Dir["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c", "lib/**/*.rb",
|
||||||
|
|
44
lib/pry.rb
44
lib/pry.rb
|
@ -4,6 +4,8 @@
|
||||||
direc = File.dirname(__FILE__)
|
direc = File.dirname(__FILE__)
|
||||||
|
|
||||||
require 'ruby_parser'
|
require 'ruby_parser'
|
||||||
|
require 'method_source'
|
||||||
|
require 'stringio'
|
||||||
require "#{direc}/pry/version"
|
require "#{direc}/pry/version"
|
||||||
require "#{direc}/pry/input"
|
require "#{direc}/pry/input"
|
||||||
require "#{direc}/pry/output"
|
require "#{direc}/pry/output"
|
||||||
|
@ -15,7 +17,7 @@ class Pry
|
||||||
|
|
||||||
def self.view(obj)
|
def self.view(obj)
|
||||||
case obj
|
case obj
|
||||||
when String, Symbol, nil
|
when String, Array, Hash, Symbol, nil
|
||||||
obj.inspect
|
obj.inspect
|
||||||
else
|
else
|
||||||
obj.to_s
|
obj.to_s
|
||||||
|
@ -150,7 +152,8 @@ class Pry
|
||||||
output.exit
|
output.exit
|
||||||
throw(:breakout, nesting.level)
|
throw(:breakout, nesting.level)
|
||||||
when "ls"
|
when "ls"
|
||||||
eval_string.replace("local_variables + instance_variables")
|
output.ls(target)
|
||||||
|
eval_string.clear
|
||||||
when /^cd\s+(.+)/
|
when /^cd\s+(.+)/
|
||||||
obj = $~.captures.first
|
obj = $~.captures.first
|
||||||
target.eval("#{obj}.pry")
|
target.eval("#{obj}.pry")
|
||||||
|
@ -184,8 +187,7 @@ class Pry
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_method_source(target, meth_name, kind)
|
def get_method_source(target, meth_name, kind)
|
||||||
file, line = target.eval("#{kind}(:#{meth_name}).source_location")
|
target.eval("#{kind}(:#{meth_name}).source")
|
||||||
Pry.new.tap { |v| v.input = SourceInput.new(file, line) }.r
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def prompt(eval_string, target, nest)
|
def prompt(eval_string, target, nest)
|
||||||
|
@ -198,27 +200,23 @@ class Pry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_expression?(code)
|
if RUBY_VERSION =~ /1.9/
|
||||||
test_bed = Object.new.instance_eval { binding }
|
require 'ripper'
|
||||||
|
|
||||||
begin
|
def valid_expression?(code)
|
||||||
test_bed.eval(code)
|
!!Ripper::SexpBuilder.new(code).parse
|
||||||
rescue SyntaxError => e
|
|
||||||
case e.message
|
|
||||||
when /(parse|syntax) error.*?\$end/i, /unterminated/i
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
rescue Exception
|
|
||||||
end
|
end
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
def old_valid_expression?(code)
|
|
||||||
RubyParser.new.parse(code)
|
|
||||||
rescue Racc::ParseError, SyntaxError
|
|
||||||
false
|
|
||||||
else
|
else
|
||||||
true
|
|
||||||
|
def valid_expression?(code)
|
||||||
|
RubyParser.new.parse(code)
|
||||||
|
rescue Racc::ParseError, SyntaxError
|
||||||
|
false
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def binding_for(target)
|
def binding_for(target)
|
||||||
|
|
|
@ -29,6 +29,10 @@ class Pry
|
||||||
puts "status Show status information"
|
puts "status Show status information"
|
||||||
puts "! Refresh the REPL"
|
puts "! Refresh the REPL"
|
||||||
puts "nesting Show nesting information"
|
puts "nesting Show nesting information"
|
||||||
|
puts "ls Show the list of variables in the current scope"
|
||||||
|
puts "cd <var> Start a Pry session on <var> (use `cd ..` to go back)"
|
||||||
|
puts "show_method <methname> Show the sourcecode for the method <method_name>"
|
||||||
|
puts "show_instance_method <methname> Show the sourcecode for the instance method <method_name>"
|
||||||
puts "exit/quit/back End the current Pry session"
|
puts "exit/quit/back End the current Pry session"
|
||||||
puts "exit_all End all nested Pry sessions"
|
puts "exit_all End all nested Pry sessions"
|
||||||
puts "exit_program/quit_program End the current program"
|
puts "exit_program/quit_program End the current program"
|
||||||
|
@ -52,10 +56,14 @@ class Pry
|
||||||
puts "--"
|
puts "--"
|
||||||
puts "Receiver: #{Pry.view(target.eval('self'))}"
|
puts "Receiver: #{Pry.view(target.eval('self'))}"
|
||||||
puts "Nesting level: #{nesting.level}"
|
puts "Nesting level: #{nesting.level}"
|
||||||
puts "Local variables: #{Pry.view(target.eval("local_variables"))}"
|
puts "Local variables: #{target.eval('Pry.view(local_variables)')}"
|
||||||
puts "Last result: #{Pry.view(Pry.last_result)}"
|
puts "Last result: #{Pry.view(Pry.last_result)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ls(target)
|
||||||
|
puts "#{target.eval('Pry.view(local_variables + instance_variables)')}"
|
||||||
|
end
|
||||||
|
|
||||||
def show_method(code)
|
def show_method(code)
|
||||||
code.display
|
code.display
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
class Pry
|
class Pry
|
||||||
VERSION = "0.2.5pre2"
|
VERSION = "0.2.6"
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue