starting to write the behemoth that is README.markdown
This commit is contained in:
parent
ebdcfdf145
commit
ead507210d
152
README.markdown
152
README.markdown
|
@ -6,7 +6,8 @@ Pry
|
|||
_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.
|
||||
manipulation of objects during the running of a program. It is primarily
|
||||
designed for examining and manipulating large and complicated runtime state.
|
||||
|
||||
It is not based on the IRB codebase, and implements some unique REPL
|
||||
commands such as `show_method` and `jump_to`
|
||||
|
@ -144,11 +145,13 @@ end.
|
|||
* Pry sessions can nest arbitrarily deeply -- to go back one level of nesting type 'exit' or 'quit' or 'back'
|
||||
* Use `_` to recover last result.
|
||||
* Use `_pry_` to reference the Pry instance managing the current session.
|
||||
* Pry supports tab completion.
|
||||
* Pry has multi-line support built in.
|
||||
* Pry has special commands not found in many other Ruby REPLs: `show_method`, `show_doc`
|
||||
`jump_to`, `ls`, `cd`, `cat`
|
||||
* Pry gives good control over nested sessions (important when exploring complicated runtime state)
|
||||
* Pry is not based on the IRB codebase.
|
||||
* Pry supports significant customizability.
|
||||
* Pry uses [RubyParser](https://github.com/seattlerb/ruby_parser) to
|
||||
validate expressions in 1.8, and [Ripper](http://rdoc.info/docs/ruby-core/1.9.2/Ripper) for 1.9.
|
||||
* Pry implements all the methods in the REPL chain separately: `Pry#r`
|
||||
|
@ -264,6 +267,153 @@ Pry instance.
|
|||
|
||||
### Input:
|
||||
|
||||
For input Pry accepts any object that implements the `readline` method. This
|
||||
includes `IO` objects, `StringIO`, `Readline` and custom objects. Pry
|
||||
initially defaults to using `Readline` for input.
|
||||
|
||||
#### Example: Setting global input
|
||||
|
||||
Setting Pry's global input causes all subsequent Pry instances to use
|
||||
this input by default:
|
||||
|
||||
Pry.input = StringIO.new("@x = 10\nexit")
|
||||
Object.pry
|
||||
|
||||
Object.instance_variable_get(:@x) #=> 10
|
||||
|
||||
The above will execute the code in the `StringIO`
|
||||
non-interactively. It gets all the input it needs from the `StringIO`
|
||||
and then exits the Pry session. Note it is important to end the
|
||||
session with 'exit' if you are running non-interactively or the Pry
|
||||
session will hang as it loops indefinitely awaiting new input.
|
||||
|
||||
#### Example: Setting input for a specific session
|
||||
|
||||
The settings for a specific session override the global settings
|
||||
(discussed above). There are two ways to set input for a specific pry session: At the
|
||||
point the session is started, or within the session itself:
|
||||
|
||||
Here is the first case:
|
||||
|
||||
Pry.start(Object, :input => StringIO.new("@x = 10\nexit"))
|
||||
Object.instance_variable_get(:@x) #=> 10
|
||||
|
||||
If you want to set the input object within the session itself you use
|
||||
the special `_pry_` local variable which represents the Pry instance
|
||||
managing the current session; inside the session we type:
|
||||
|
||||
_pry_.input = StringIO.new("@x = 10\nexit")
|
||||
|
||||
### Output
|
||||
|
||||
For output Pry accepts any object that implements the `puts` method. This
|
||||
includes `IO` objects, `StringIO` and custom objects. Pry initially
|
||||
defaults to using `$stdout` for output.
|
||||
|
||||
#### Example: Setting global output
|
||||
|
||||
Setting Pry's global output causes all subsequent Pry instances to use
|
||||
this output by default:
|
||||
|
||||
Pry.output = StringIO.new
|
||||
Object.pry
|
||||
|
||||
Object.instance_variable_get(:@x) #=> 10
|
||||
|
||||
#### Example: Setting output for a specific session
|
||||
|
||||
As per Input, given above, we set the local output as follows:
|
||||
|
||||
Here is the first case:
|
||||
|
||||
Pry.start(Object, :output => StringIO.new("@x = 10\nexit"))
|
||||
Object.instance_variable_get(:@x) #=> 10
|
||||
|
||||
And to change output from within the session itself:
|
||||
|
||||
_pry_.output = StringIO.new
|
||||
|
||||
### Commands
|
||||
|
||||
Pry commands are not methods; they are commands that are intercepted
|
||||
and executed before a Ruby eval takes place. Pry comes with a default
|
||||
command set, but these commands can be augmented or overriden by
|
||||
user-specified ones.
|
||||
|
||||
A valid Pry command object must inherit from
|
||||
`Pry::CommandBase` and use the special command API:
|
||||
|
||||
#### Example: Defining a command object and setting it globally
|
||||
|
||||
class MyCommands < Pry::CommandBase
|
||||
command "hello" do
|
||||
pattern /^hello\s*(.+)/
|
||||
describe "Output hello to the user."
|
||||
action do |opts|
|
||||
opts[:output].puts "hello #{opts[:captures].first}!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Pry.commands = MyCommands
|
||||
|
||||
Then inside a pry session:
|
||||
|
||||
(pry)> hello john
|
||||
hello john!
|
||||
=> nil
|
||||
|
||||
#### Example: Using a command object in a specific session
|
||||
|
||||
As in the case of `input` and `output`:
|
||||
|
||||
At session start:
|
||||
|
||||
Pry.start(self, :commands => MyCommands)
|
||||
|
||||
From within the session:
|
||||
|
||||
_pry_.commands = MyCommands
|
||||
|
||||
#### The command API
|
||||
|
||||
The command API is defined by the `Pry::CommandBase` class (hence why
|
||||
all commands must inherit from it). The API works as follows:
|
||||
|
||||
The `command` method defines a new command, its parameter is the
|
||||
name of the command. The block associated with `command` supports the
|
||||
following methods, and defines the substance of the command:
|
||||
|
||||
* `describe(str)` - Used to describe the functionality of the command;
|
||||
used with `help`.
|
||||
* `action(&block)` - Defines the action to perform when the command is invoked.
|
||||
* `pattern(regex)` - If `pattern` is used then the command shall be
|
||||
invoked if user input matches this pattern (rather than just the
|
||||
command name). Any captures defined in the pattern can be accessed
|
||||
in the action block through the `opts[:captures]` hash parameter.
|
||||
|
||||
#### action block parameters
|
||||
|
||||
Note that in the example we are using `opts[:output]` for output; this is the output
|
||||
object in use by the current pry session. Other hash values accesible
|
||||
within an `action` block include:
|
||||
|
||||
* `opts[:output]` - The session's output object.
|
||||
* `opts[:val]` - The line of input that invoked the command.
|
||||
* `opts[:eval_string]` - The cumulative lines of input for multi-line input.
|
||||
* `opts[:target]` - The object the Pry session is currently on.
|
||||
* `opts[:captures]` - The array of regex captures generated by the command (if any).
|
||||
* `opts[:nesting]` - Lowlevel session nesting information.
|
||||
* `opts[:command_info]` - Lowlevel information about all Pry commands.
|
||||
|
||||
(see commands.rb for examples of how some of these options are used)
|
||||
|
||||
#### The `help` command
|
||||
|
||||
The `Pry::CommandBase` class automatically defines a `help` command
|
||||
for you. Typing `help` in a Pry session will show a list of commands
|
||||
to the user followed by their descriptions. Passing a parameter to
|
||||
`help` with the command name will just return the description of that specific command.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
class Pry
|
||||
|
||||
# Basic command functionality. All user-defined commands must
|
||||
# inherit from this class. It provides the `command` method.
|
||||
class CommandBase
|
||||
class << self
|
||||
attr_accessor :commands
|
||||
attr_accessor :command_info
|
||||
end
|
||||
|
||||
# A class to assist in building Pry commands
|
||||
class Command
|
||||
Elements = [:name, :describe, :pattern, :action]
|
||||
|
||||
|
@ -14,12 +17,14 @@ class Pry
|
|||
define_method("get_#{e}") { instance_variable_get("@#{e}") }
|
||||
end
|
||||
|
||||
# define action here since it needs to take a block
|
||||
# define action here since it needs to take a block.
|
||||
def action(&block)
|
||||
@action = block
|
||||
end
|
||||
end
|
||||
|
||||
# Ensure commands are properly constructed.
|
||||
# @param [Pry::CommandBase::Command] c The command to check.
|
||||
def self.check_command(c)
|
||||
c.pattern(c.get_name) if !c.get_pattern
|
||||
c.describe "No description." if !c.get_describe
|
||||
|
@ -29,6 +34,11 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
# Defines a new Pry command.
|
||||
# @param [String, Array] name The name of the command (or array of
|
||||
# command name aliases).
|
||||
# @yield [command] The command block. Optionall yields command if
|
||||
# block arity is 1. Otherwise block is instance_eval'd.
|
||||
def self.command(name, &block)
|
||||
@commands ||= {}
|
||||
@command_info ||= {}
|
||||
|
@ -36,12 +46,16 @@ class Pry
|
|||
c = Command.new
|
||||
c.name name
|
||||
|
||||
c.instance_eval(&block)
|
||||
if block.arity == 1
|
||||
yield(c)
|
||||
else
|
||||
c.instance_eval(&block)
|
||||
end
|
||||
|
||||
check_command(c)
|
||||
|
||||
@commands.merge! c.get_pattern => c.get_action
|
||||
@command_info.merge! c.get_name => c.get_describe
|
||||
commands.merge! c.get_pattern => c.get_action
|
||||
command_info.merge! c.get_name => c.get_describe
|
||||
end
|
||||
|
||||
command "help" do
|
||||
|
@ -57,7 +71,7 @@ class Pry
|
|||
out.puts "Command list:"
|
||||
out.puts "--"
|
||||
command_info.each do |k, v|
|
||||
puts "#{Array(k).first}".ljust(18) + v
|
||||
out.puts "#{Array(k).first}".ljust(18) + v
|
||||
end
|
||||
else
|
||||
key = command_info.keys.find { |v| Array(v).any? { |k| k === param } }
|
||||
|
|
|
@ -5,44 +5,29 @@ class Pry
|
|||
# Default commands used by Pry.
|
||||
# @note
|
||||
# If you plan to replace the default Commands class with a custom
|
||||
# one then it must have a `commands` method that returns a Hash.
|
||||
# one then it must be a class that inherits from
|
||||
# `Pry::CommandBase` or from `Pry::Commands` (if you want to keep
|
||||
# default commands).
|
||||
# @example Creating a custom command set
|
||||
# class MyCommands < Pry::CommandBase
|
||||
# command "greeting" do
|
||||
# describe "give a greeting"
|
||||
# action { puts "hello world!" }
|
||||
# end
|
||||
#
|
||||
# command "goodbye" do
|
||||
# describe "say goodbye and quit"
|
||||
# action { puts "goodbye!"; exit }
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# Pry.commands = MyCommands
|
||||
class Commands < CommandBase
|
||||
|
||||
# This method returns a hash that defines the commands implemented for the REPL session.
|
||||
# The hash has the following form:
|
||||
#
|
||||
# * Each key is a command, it should either be a String or a
|
||||
# Regexp or an Array.
|
||||
# * Where it is an Array, each element should be a String or a
|
||||
# Regexp, and the elements are considered to be aliases.
|
||||
# * Each value is the action to take for the command. The value
|
||||
# should be a `proc`.
|
||||
# * If the proc needs to generate output it should write to the
|
||||
# `opts[:output]` object, as follows: `opts[:output].puts "hello world"`
|
||||
# * When the proc is invoked it is passed parameters in the form
|
||||
# of an options hash, the parameters are as follows:
|
||||
#
|
||||
# * `opts[:val]` The current line of input.
|
||||
# * `opts[:eval_string]` The cumulative lines of input for a multi-line input.
|
||||
# * `opts[:target]` The receiver of the Pry session.
|
||||
# * `opts[:nesting]` The nesting level of the current Pry Session.
|
||||
# * `opts[:output]` The `output` object for the current Pry session.
|
||||
# * `opts[:captures]` The Regexp captures for the command (if
|
||||
# any) - This can be used to implement command parameters.
|
||||
#
|
||||
# @return [Hash] The commands hash.
|
||||
# @example A 'hello' command.
|
||||
# def commands
|
||||
# {
|
||||
# /^hello\s*(.+)/ => proc do |opts|
|
||||
# opts[:output].puts "hello #{opts[:captures].first}"
|
||||
# }
|
||||
# end
|
||||
command "!" do
|
||||
describe "Refresh the REPL"
|
||||
action do |opts|
|
||||
opts[:output].puts "Refreshed REPL"
|
||||
|
||||
opts[:eval_string].clear
|
||||
end
|
||||
end
|
||||
|
@ -51,7 +36,6 @@ class Pry
|
|||
describe "Start a Pry session on current self; this even works mid-expression."
|
||||
action do |opts|
|
||||
Pry.start(opts[:target])
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -76,8 +60,6 @@ class Pry
|
|||
out.puts "#{level}. #{Pry.view(obj)}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class Pry
|
|||
attr_accessor :active_instance
|
||||
|
||||
# Get/Set the object to use for input by default by all Pry instances.
|
||||
# @return [#read] The object to use for input by default by all
|
||||
# @return [#readline] The object to use for input by default by all
|
||||
# Pry instances.
|
||||
attr_accessor :input
|
||||
|
||||
|
@ -32,7 +32,7 @@ class Pry
|
|||
attr_accessor :output
|
||||
|
||||
# Get/Set the object to use for commands by default by all Pry instances.
|
||||
# @return [#commands] The object to use for commands by default by all
|
||||
# @return [Pry::CommandBase] The object to use for commands by default by all
|
||||
# Pry instances.
|
||||
attr_accessor :commands
|
||||
|
||||
|
@ -43,7 +43,6 @@ class Pry
|
|||
# Pry instances.
|
||||
attr_accessor :print
|
||||
|
||||
|
||||
# Get/Set the Hash that defines Pry hooks used by default by all Pry
|
||||
# instances.
|
||||
# @return [Hash] The hooks used by default by all Pry instances.
|
||||
|
|
|
@ -10,7 +10,7 @@ class Pry
|
|||
|
||||
# Create a new `Pry` object.
|
||||
# @param [Hash] options The optional configuration parameters.
|
||||
# @option options [#read] :input The object to use for input. (see input.rb)
|
||||
# @option options [#readline] :input The object to use for input. (see input.rb)
|
||||
# @option options [#puts] :output The object to use for output. (see output.rb)
|
||||
# @option options [Pry::CommandBase] :commands The object to use for
|
||||
# commands. (see commands.rb)
|
||||
|
|
Loading…
Reference in New Issue