version 0.5.0pre4 Almost ready for release. Updated examples to match new changes, updated README.

This commit is contained in:
John Mair 2011-02-17 10:22:59 +13:00
parent f8f0919189
commit 42d1c126af
7 changed files with 146 additions and 96 deletions

View File

@ -13,7 +13,7 @@ session to your code (with Pry) instead of bringing your code to a
REPL session (as with IRB). REPL session (as with IRB).
It is not based on the IRB codebase, and implements some unique REPL It is not based on the IRB codebase, and implements some unique REPL
commands such as `show_method` and `show_doc` commands such as `show-method`, `show-doc`, `ls` and `cd`
Pry is also fairly flexible and allows significant user Pry is also fairly flexible and allows significant user
[customization](http://rdoc.info/github/banister/pry/master/file/wiki/Customizing-pry.md). It [customization](http://rdoc.info/github/banister/pry/master/file/wiki/Customizing-pry.md). It
@ -121,9 +121,9 @@ command. E.g
=> nil => nil
We can then jump back to any of the previous nesting levels by using We can then jump back to any of the previous nesting levels by using
the `jump_to` command: the `jump-to` command:
pry("friend":3)> jump_to 1 pry("friend":3)> jump-to 1
Ending Pry session for "friend" Ending Pry session for "friend"
Ending Pry session for 100 Ending Pry session for 100
=> 100 => 100
@ -133,9 +133,9 @@ If we just want to go back one level of nesting we can of course
use the `quit` or `exit` or `back` commands. use the `quit` or `exit` or `back` commands.
To break out of all levels of Pry nesting and return immediately to the To break out of all levels of Pry nesting and return immediately to the
calling process use `exit_all`: calling process use `exit-all`:
pry("friend":3)> exit_all pry("friend":3)> exit-all
Ending Pry session for "friend" Ending Pry session for "friend"
Ending Pry session for 100 Ending Pry session for 100
Ending Pry session for Hello Ending Pry session for Hello
@ -163,8 +163,8 @@ end.
* Use `_pry_` to reference the Pry instance managing the current session. * Use `_pry_` to reference the Pry instance managing the current session.
* Pry supports tab completion. * Pry supports tab completion.
* Pry has multi-line support built in. * Pry has multi-line support built in.
* Pry has special commands not found in many other Ruby REPLs: `show_method`, `show_doc` * Pry has special commands not found in many other Ruby REPLs: `show-method`, `show-doc`
`jump_to`, `ls`, `cd`, `cat` `jump-to`, `ls`, `cd`, `cat`
* 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 allows significant customizability. * Pry allows significant customizability.
@ -183,7 +183,7 @@ invoke any of these methods directly depending on exactly what aspect of the fun
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)
* Pry's `show_method` and `show_doc` commands do not work * Pry's `show-method` and `show-doc` commands do not work
in Ruby 1.8. in Ruby 1.8.
Commands Commands
@ -229,35 +229,34 @@ whitespace in between.
If you want to access a method of the same name, prefix the invocation by whitespace. 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 * Typing `!` on a line by itself will clear the input buffer - useful for
getting you out of a situation if the parsing process getting you out of a situation where the parsing process
goes wrong. goes wrong and you get stuck in an endless read loop.
* `status` shows status information about the current session. * `status` shows status information about the current session.
* `version` Show Pry version information
* `help` shows the list of session commands with brief explanations. * `help` shows the list of session commands with brief explanations.
* `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 * `ls [OPTIONS] [VAR]` returns a list of local variables, instance variables, and
current scope methods, etc. Highly flexible. See `ls --help` for more info.
* `ls_methods` List all methods defined on immediate class of receiver. * `cat VAR` Calls `inspect` on `VAR`
* `ls_imethods` List all instance methods defined on receiver. * `cd VAR` Starts a `Pry` session on the variable VAR. E.g `cd @x`
* `cat <var>` Calls `inspect` on `<var>`
* `cd <var>` Starts a `Pry` session on the variable <var>. E.g `cd @x`
(use `cd ..` to go back). (use `cd ..` to go back).
* `show_method <methname>` Displays the sourcecode for the method * `show-method [OPTIONS] METH` Displays the sourcecode for the method
<methname>. E.g `show_method hello` `METH`. E.g `show-method hello`. See `show-method --help` for more info.
* `show_imethod <methname>` Displays the sourcecode for the * `show-doc [OPTIONS] METH` Displays comments for `METH`. See `show-doc
instance method <methname>. E.g `show_imethod goodbye` --help` for more info.
* `show_doc <methname>` Displays comments for `<methname>` * `exit-program` or `quit-program` will end the currently running
* `show_idoc <methname>` Displays comments for instance
method `<methname>`
* `exit_program` or `quit_program` will end the currently running
program. program.
* `nesting` Shows Pry nesting information. * `nesting` Shows Pry nesting information.
* `cat-file FILE` Displays the contents of a file on disk in the Pry session.
* `eval-file [OPTIONS] FILE` Evals a Ruby script at top-level or in
the current context. See `eval-file --help` for more info.
* `!pry` Starts a Pry session on the implied receiver; this can be * `!pry` Starts a Pry session on the implied receiver; this can be
used in the middle of an expression in multi-line input. used in the middle of an expression in multi-line input.
* `jump_to <nest_level>` Unwinds the Pry stack (nesting level) until the appropriate nesting level is reached. * `jump-to NEST_LEVEL` Unwinds the Pry stack (nesting level) until the appropriate nesting level is reached.
* `exit_all` breaks out of all Pry nesting levels and returns to the * `exit-all` breaks out of all Pry nesting levels and returns to the
calling process. calling process.
* You can type `Pry.start(obj)` or `obj.pry` to nest another Pry session within the * 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 current one with `obj` as the receiver of the new session. Very useful
@ -308,7 +307,3 @@ Contact
------- -------
Problems or questions contact me at [github](http://github.com/banister) Problems or questions contact me at [github](http://github.com/banister)

1
TODO
View File

@ -12,5 +12,4 @@
* add --help option to most commands * add --help option to most commands
* Get rid of ls_method and ls_imethods (subsumed by more powerful ls) * Get rid of ls_method and ls_imethods (subsumed by more powerful ls)
* Get rid of show_idoc and show_imethod * Get rid of show_idoc and show_imethod
* Support YARD and Rdoc documentation
* Add special load-file command that evals target file in current context * Add special load-file command that evals target file in current context

View File

@ -27,7 +27,7 @@ class MyCommands < Pry::CommandBase
end end
# bring in a few other commands # bring in a few other commands
import_from Pry::Commands, "quit", "show_method" import_from Pry::Commands, "quit", "show-method"
end end
# Start a Pry session using the commands defined in MyCommands # Start a Pry session using the commands defined in MyCommands

View File

@ -31,23 +31,23 @@ class ImageCommands < Pry::CommandBase
exit exit
end end
import_from Pry::Commands, "ls", "ls_methods", "!" import_from Pry::Commands, "ls", "!"
end end
class WinClass < Gosu::Window class WinClass < Gosu::Window
def initialize def initialize
super(WIDTH, HEIGHT, false) super(WIDTH, HEIGHT, false)
$img = TexPlay.create_image(self, 200, 200).clear :color => :black @img = TexPlay.create_image(self, 200, 200).clear :color => :black
$img.rect 0, 0, $img.width - 1, $img.height - 1 @img.rect 0, 0, @img.width - 1, @img.height - 1
@binding = $img.__binding__ @binding = Pry.binding_for(@img)
@pry_instance = Pry.new(:commands => ImageCommands, :prompt => IMAGE_PROMPT) @pry_instance = Pry.new(:commands => ImageCommands, :prompt => IMAGE_PROMPT)
end end
def draw def draw
$img.draw_rot(WIDTH / 2, HEIGHT / 2, 1, 0, 0.5, 0.5) @img.draw_rot(WIDTH / 2, HEIGHT / 2, 1, 0, 0.5, 0.5)
end end
def update def update
@ -57,7 +57,7 @@ class WinClass < Gosu::Window
# being updated; instead we do a REP session, and let the image # being updated; instead we do a REP session, and let the image
# update each time the user presses enter. We maintain the same # update each time the user presses enter. We maintain the same
# binding object to keep locals between calls to `Pry#rep()` # binding object to keep locals between calls to `Pry#rep()`
# @pry_instance.rep(@binding) @pry_instance.rep(@binding)
end end
end end
@ -67,6 +67,5 @@ puts "Example: Try typing 'circle width/2, height/2, 95, :color => :blue, :fill
puts "If you want to save your image, type: save(\"img.png\")" puts "If you want to save your image, type: save(\"img.png\")"
w = WinClass.new w = WinClass.new
Thread.new { Pry.start(w) }
w.show w.show

View File

@ -13,7 +13,7 @@ nesting
puts 'hello from 2!!' puts 'hello from 2!!'
_pry_.parent.input = Readline _pry_.parent.input = Readline
back back
exit_all exit-all
CMDS CMDS
# create our StringIO object # create our StringIO object

View File

@ -17,7 +17,7 @@ class Pry
end end
end end
command "!", "Clear the input buffer. Useful if the parsing process goes wrong." do command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop." do
output.puts "Input buffer cleared!" output.puts "Input buffer cleared!"
opts[:eval_string].clear opts[:eval_string].clear
end end
@ -33,35 +33,33 @@ class Pry
alias_command "quit-program", "exit-program", "" alias_command "quit-program", "exit-program", ""
command "nesting", "Show nesting information." do command "nesting", "Show nesting information." do
out = output
nesting = opts[:nesting] nesting = opts[:nesting]
out.puts "Nesting status:" output.puts "Nesting status:"
out.puts "--" output.puts "--"
nesting.each do |level, obj| nesting.each do |level, obj|
if level == 0 if level == 0
out.puts "#{level}. #{Pry.view_clip(obj)} (Pry top level)" output.puts "#{level}. #{Pry.view_clip(obj)} (Pry top level)"
else else
out.puts "#{level}. #{Pry.view_clip(obj)}" output.puts "#{level}. #{Pry.view_clip(obj)}"
end end
end end
end end
command "status", "Show status information." do command "status", "Show status information." do
out = output
nesting = opts[:nesting] nesting = opts[:nesting]
out.puts "Status:" output.puts "Status:"
out.puts "--" output.puts "--"
out.puts "Receiver: #{Pry.view_clip(target.eval('self'))}" output.puts "Receiver: #{Pry.view_clip(target.eval('self'))}"
out.puts "Nesting level: #{nesting.level}" output.puts "Nesting level: #{nesting.level}"
out.puts "Pry version: #{Pry::VERSION}" output.puts "Pry version: #{Pry::VERSION}"
out.puts "Ruby version: #{RUBY_VERSION}" output.puts "Ruby version: #{RUBY_VERSION}"
mn = meth_name_from_binding.call(target) mn = meth_name_from_binding.call(target)
out.puts "Current method: #{mn ? mn : "N/A"}" output.puts "Current method: #{mn ? mn : "N/A"}"
out.puts "Pry instance: #{Pry.active_instance}" output.puts "Pry instance: #{Pry.active_instance}"
out.puts "Last result: #{Pry.view(Pry.last_result)}" output.puts "Last result: #{Pry.view(Pry.last_result)}"
end end
command "version", "Show Pry version." do command "version", "Show Pry version." do
@ -82,51 +80,46 @@ class Pry
OptionParser.new do |opts| OptionParser.new do |opts|
opts.banner = %{Usage: ls [OPTIONS] [VAR]\n\ opts.banner = %{Usage: ls [OPTIONS] [VAR]\n\
List information about VAR (the current context by default). List information about VAR (the current context by default).
Always shows local and instance variables by default; use -r to restrict to specific types. Shows local and instance variables by default.
-- --
} }
opts.on("-g", "--globals", "Display global variables.") do
opts.on("-g", "--globals", "Display global variables.") do |g|
options[:g] = true options[:g] = true
end end
opts.on("-c", "--constants", "Display constants.") do |c| opts.on("-c", "--constants", "Display constants.") do
options[:c] = true options[:c] = true
end end
opts.on("-l", "--locals", "Display locals.") do |c| opts.on("-l", "--locals", "Display locals.") do
options[:l] = true options[:l] = true
end end
opts.on("-i", "--ivars", "Display instance variables.") do |c| opts.on("-i", "--ivars", "Display instance variables.") do
options[:i] = true options[:i] = true
end end
opts.on("-k", "--class-vars", "Display class variables.") do |c| opts.on("-k", "--class-vars", "Display class variables.") do
options[:k] = true options[:k] = true
end end
opts.on("-m", "--methods", "Display methods.") do |c| opts.on("-m", "--methods", "Display methods.") do
options[:m] = true options[:m] = true
end end
opts.on("-M", "--instance-methods", "Display instance methods (only relevant to classes and modules).") do |c| opts.on("-M", "--instance-methods", "Display instance methods (only relevant to classes and modules).") do
options[:M] = true options[:M] = true
end end
opts.on("-s", "--super", "Include superclass entries (relevant to constant and methods options).") do |c| opts.on("-s", "--super", "Include superclass entries (relevant to constant and methods options).") do
options[:s] = true options[:s] = true
end end
opts.on("-r", "--restrict", "Restrict to specified types.") do |c| opts.on("-a", "--all", "Display all types of entries.") do
options[:r] = true
end
opts.on("-a", "--all", "Display all types of entries.") do |a|
options[:a] = true options[:a] = true
end end
opts.on("-v", "--verbose", "Verbose ouput.") do |c| opts.on("-v", "--verbose", "Verbose ouput.") do
options[:v] = true options[:v] = true
end end
@ -141,6 +134,14 @@ Always shows local and instance variables by default; use -r to restrict to spec
# exit if we've displayed help # exit if we've displayed help
next if options[:h] next if options[:h]
# default is locals/ivars/class vars.
# Only occurs when no options or when only option is verbose
options.merge!({
:l => true,
:i => true,
:k => true
}) if options.empty? || (options.size == 1 && options[:v])
info = {} info = {}
target_self = target.eval('self') target_self = target.eval('self')
@ -148,23 +149,29 @@ Always shows local and instance variables by default; use -r to restrict to spec
# interpolating in the string) # interpolating in the string)
options[:s] = !!options[:s] options[:s] = !!options[:s]
# Numbers (e.g 0, 1, 2) are for ordering the hash values in Ruby # Numbers (e.g 0, 1, 2) are for ordering the hash values in Ruby 1.8
# 1.8
i = -1 i = -1
info["local variables"] = Array(target.eval("local_variables")).sort, i += 1 if !options[:r] || options[:l] || options[:a]
info["instance variables"] = Array(target.eval("instance_variables")).sort, i += 1 if !options[:r] || options[:i] || options[:a]
info["class variables"] = (target_self.is_a?(Module) ? Array(target.eval("class_variables")).sort : Array(target.eval("self.class.class_variables")).sort), i += 1 if !options[:r] || options[:k] || options[:a]
info["global variables"] = Array(target.eval("global_variables")).sort, i += 1 if options[:g] || options[:a] # Start collecting the entries selected by the user
info["local variables"] = [Array(target.eval("local_variables")).sort, i += 1] if options[:l] || options[:a]
info["instance variables"] = [Array(target.eval("instance_variables")).sort, i += 1] if options[:i] || options[:a]
info["methods"] = Array(target.eval("methods(#{options[:s]}) + public_methods(#{options[:s]}) +\ info["class variables"] = [if target_self.is_a?(Module)
Array(target.eval("class_variables")).sort
else
Array(target.eval("self.class.class_variables")).sort
end, i += 1] if options[:k] || options[:a]
info["global variables"] = [Array(target.eval("global_variables")).sort, i += 1] if options[:g] || options[:a]
info["methods"] = [Array(target.eval("methods(#{options[:s]}) + public_methods(#{options[:s]}) +\
protected_methods(#{options[:s]}) +\ protected_methods(#{options[:s]}) +\
private_methods(#{options[:s]})")).uniq.sort, i += 1 if options[:m] || options[:a] private_methods(#{options[:s]})")).uniq.sort, i += 1] if options[:m] || options[:a]
info["instance methods"] = Array(target.eval("instance_methods(#{options[:s]}) +\ info["instance methods"] = [Array(target.eval("instance_methods(#{options[:s]}) +\
public_instance_methods(#{options[:s]}) +\ public_instance_methods(#{options[:s]}) +\
protected_instance_methods(#{options[:s]}) +\ protected_instance_methods(#{options[:s]}) +\
private_instance_methods(#{options[:s]})")).uniq.sort, i += 1 if target_self.is_a?(Module) && (options[:M] || options[:a]) private_instance_methods(#{options[:s]})")).uniq.sort, i += 1] if target_self.is_a?(Module) && (options[:M] || options[:a])
# dealing with 1.8/1.9 compatibility issues :/ # dealing with 1.8/1.9 compatibility issues :/
csuper = options[:s] csuper = options[:s]
@ -172,8 +179,8 @@ Always shows local and instance variables by default; use -r to restrict to spec
csuper = nil csuper = nil
end end
info["constants"] = Array(target_self.is_a?(Module) ? target.eval("constants(#{csuper})") : info["constants"] = [Array(target_self.is_a?(Module) ? target.eval("constants(#{csuper})") :
target.eval("self.class.constants(#{csuper})")).uniq.sort, i += 1 if options[:c] || options[:a] target.eval("self.class.constants(#{csuper})")).uniq.sort, i += 1] if options[:c] || options[:a]
# verbose output? # verbose output?
if options[:v] if options[:v]
@ -193,13 +200,63 @@ Always shows local and instance variables by default; use -r to restrict to spec
end end
end end
command "cat-file", "Show output of file FILE" do |file_name|
if !file_name
output.puts "Must provide a file name."
next
end
output.puts File.read(file_name)
end
command "eval-file", "Eval a Ruby script. Type `eval-file --help` for more info." do |*args|
options = {}
file_name = nil
OptionParser.new do |opts|
opts.banner = %{Usage: eval-file [OPTIONS] FILE
Eval a Ruby script at top-level or in the current context.
e.g: eval-script -c "hello.rb"
--
}
opts.on("-c", "--context", "Eval the script in the current context.") do
options[:c] = true
end
opts.on_tail("-h", "--help", "This message.") do
output.puts opts
options[:h] = true
end
end.order(args) do |v|
file_name = v
end
next if options[:h]
if !file_name
output.puts "You need to specify a file name. Type `eval-script --help` for help"
next
end
old_constants = Object.constants
if options[:c]
target.eval(File.read(file_name))
output.puts "--\nEval'd '#{file_name}' in the current context."
else
TOPLEVEL_BINDING.eval(File.read(file_name))
output.puts "--\nEval'd '#{file_name}' at top-level."
end
new_constants = Object.constants - old_constants
output.puts "Brought in the following top-level constants: #{new_constants.inspect}" if !new_constants.empty?
end
command "cat", "Show output of VAR.inspect. Aliases: inspect" do |obj| command "cat", "Show output of VAR.inspect. Aliases: inspect" do |obj|
if !obj if !obj
output.puts "Must provide an object to inspect." output.puts "Must provide an object to inspect."
next next
end end
output.puts target.eval("#{obj}.inspect") output.puts Pry.view(target.eval("#{obj}"))
end end
alias_command "inspect", "cat", "" alias_command "inspect", "cat", ""
@ -224,11 +281,11 @@ Show the comments above method METH. Shows _method_ comments (rather than instan
e.g show-doc hello_method e.g show-doc hello_method
-- --
} }
opts.on("-M", "--instance-methods", "Operate on instance methods instead.") do |m| opts.on("-M", "--instance-methods", "Operate on instance methods instead.") do
options[:M] = true options[:M] = true
end end
opts.on_tail("-h", "--help", "This message.") do |h| opts.on_tail("-h", "--help", "This message.") do
output.puts opts output.puts opts
options[:h] = true options[:h] = true
end end
@ -256,7 +313,7 @@ e.g show-doc hello_method
doc = meth.comment doc = meth.comment
file, line = meth.source_location file, line = meth.source_location
output.puts "From #{file} @ line ~#{line}:" output.puts "From #{file} @ line ~#{line}:\n--"
output.puts doc output.puts doc
end end
@ -270,11 +327,11 @@ Show the source for method METH. Shows _method_ source (rather than instance met
e.g: show-method hello_method e.g: show-method hello_method
-- --
} }
opts.on("-M", "--instance-methods", "Operate on instance methods instead.") do |m| opts.on("-M", "--instance-methods", "Operate on instance methods instead.") do
options[:M] = true options[:M] = true
end end
opts.on_tail("-h", "--help", "This message.") do |h| opts.on_tail("-h", "--help", "This message.") do
output.puts opts output.puts opts
options[:h] = true options[:h] = true
end end
@ -305,7 +362,7 @@ e.g: show-method hello_method
code = meth.source code = meth.source
file, line = meth.source_location file, line = meth.source_location
output.puts "From #{file} @ line #{line}:" output.puts "From #{file} @ line #{line}:\n--"
output.puts code output.puts code
end end
@ -321,7 +378,7 @@ e.g: show-method hello_method
meth = cmds[command_name][:action] meth = cmds[command_name][:action]
code = meth.source code = meth.source
file, line = meth.source_location file, line = meth.source_location
output.puts "From #{file} @ line #{line}:" output.puts "From #{file} @ line #{line}:\n--"
output.puts code output.puts code
else else
output.puts "No such command: #{command_name}." output.puts "No such command: #{command_name}."

View File

@ -1,3 +1,3 @@
class Pry class Pry
VERSION = "0.5.0pre2" VERSION = "0.5.0pre4"
end end