starting to write the behemoth that is README.markdown

This commit is contained in:
John Mair 2011-01-13 00:03:45 +11:00
parent ebdcfdf145
commit ead507210d
5 changed files with 190 additions and 45 deletions

View File

@ -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.

View File

@ -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 } }

View File

@ -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

View File

@ -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.

View File

@ -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)