1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

Merge branch 'master' into FixCommandPrefix

This commit is contained in:
yui-knk 2014-02-15 20:39:30 +09:00
commit 80e3881c67
82 changed files with 2411 additions and 2194 deletions

View file

@ -1,15 +1,17 @@
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- 2.0.0
- 2.1.0
- ruby-head
- ree
- rbx
- jruby-18mode
- jruby-19mode
- jruby
- jruby-head
script:
- rake spec
- bundle exec bacon spec/isolation/readline_spec.rb
matrix:
allow_failures:
- rvm: ruby-head

View file

@ -1,8 +1,11 @@
### 1.0.0 (2013/??/??)
#### Dependency changes
* 1.8 support discontinued from 0.10/1.0 up. 0.9 branch continues 1.8 support.
* Require Coderay `>= 1.1.0`
#### Features
* Added a `watch` command that lets you see how values change over time.
* Added an experimental `Pry.auto_resize!` method
* Makes Pry notice that your window has resized and tell Readline about it
* Fixes various bugs with command history after a window resize
@ -17,8 +20,12 @@
* User can whitelist objects whose inspect output should appear in prompt (#885)
* See `Pry.config.prompt_safe_objects`
* `whereami` is now aliased to `@`
* default configuration(Pry.config) lazy loads its values. (#1096)
* require of 'readline' is delayed until Pry.start() has been called for the first time. (#1117)
* add option to disable input completer through `_pry_.config.completer = nil`
#### Bug fixes, etc.
* `binding.pry` inside `.pryrc` file now works, with some limitations (@richo / #1118)
* Add support for BasicObjects to `ls` (#984)
* Allow `ls -c <anything>` (#891)
* Fix indentation not working if the `mathn` stdlib was loaded (#872)
@ -36,8 +43,16 @@
being inferred from context (#877)
* Rename `--installed-plugins` flag to `--plugins`
* Strip ANSI codes from prompt before measuring length for indentation (#493)
* Fix bug in `edit` regarding recognition of file names without suffix.
#### Dev-facing changes
* CommandSet#commands, sometimes referenced through Pry.commands.commands, renamed as 'CommandSet#to_hash'.
it returns a duplicate of the internal hash a CommandSet uses.
* CommandSet#keys is now an alias of CommandSet#list_commands.
* through changes to configuration, all commands should reference configuration values
via `_pry_.config` and not `Pry.config`. (#1096)
* improve configuration(Pry::Config) for easier support of concurrent environments
through a 'pry-local' config who, at times, acts as a 'pry-local store'. (#1096)
* `rake pry` now accepts switches prefixed with `_` (e.g., `rake pry _v`)
* Pagers now act like `IO`s and accept streaming output
* See `Pager.page` and `Pager.with_pager`
@ -58,6 +73,15 @@
methods of determining the terminal's dimensions
* Add `ReplTester` class for high-level simulation of Pry sessions in tests
### 0.9.12.6 (2014/01/28)
* Don't fail if Bond is not installed (#1106)
### 0.9.12.5 (2014/01/27)
* Fix early readline errors by deferring require of readline (#1081, #1095)
### 0.9.12.4 (2013/11/23)
* Fix issue with Coderay colors being black, even when on a black background (#1016)
### 0.9.12.3 (2013/09/11)
* Bump Coderay dependency (#987)
* Fix consecutive newlines in heredocs being collapsed (#962)

View file

@ -2,6 +2,7 @@
372 Conrad Irwin
215 Ryan Fitzgerald
108 Kyrylo Silin
yui-knk
92 Rob Gleeson
54 Mon ouïe
51 Lee Jarvis

View file

@ -8,7 +8,7 @@ group :development do
gem 'rb-fsevent', :require => 'false'
end
if RbConfig::CONFIG['ruby_install_name'] == 'rbx'
platform :rbx do
gem 'rubysl-singleton'
gem 'rubysl-prettyprint'
gem 'rb-readline'

View file

@ -37,7 +37,6 @@ including:
* Exotic object support (BasicObject instances, IClasses, ...)
* A Powerful and flexible command system
* Ability to view and replay history
* Many convenience commands inspired by IPython, Smalltalk and other advanced REPLs
* A wide-range number of [plugins](https://github.com/pry/pry/wiki/Available-plugins) that provide remote sessions, full debugging functionality, and more.
@ -66,13 +65,6 @@ methods. The additional docs are accessed through the `show-doc` and
* Read the [YARD API documentation](http://rdoc.info/github/pry/pry/master/file/README.markdown)
* See the [source code](http://github.com/pry/pry)
Pry also has `rubygems-test` support; to participate, first install
Pry, then:
1. Install rubygems-test: `gem install rubygems-test`
2. Run the test: `gem test pry`
3. Finally choose 'Yes' to upload the results.
### Commands
Nearly every piece of functionality in a Pry session is implemented as
@ -103,9 +95,9 @@ an instance variable inside that class:
pry(Hello):1> ls -i
instance variables: @x
pry(Hello):1> cd @x
pry(20:2)> self + 10
pry(20):2> self + 10
=> 30
pry(20:2)> cd ..
pry(20):2> cd ..
pry(Hello):1> cd ..
pry(main)> cd ..
@ -113,7 +105,7 @@ 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
pry("friend"):3> nesting
Nesting status:
0. main (Pry top level)
1. Hello
@ -124,7 +116,7 @@ command. E.g
We can then jump back to any of the previous nesting levels by using
the `jump-to` command:
pry("friend":3)> jump-to 1
pry("friend"):3> jump-to 1
=> 100
pry(Hello):1>
@ -225,7 +217,7 @@ In the following example we will enter the `Pry` class, list the
instance methods beginning with 're' and display the source code for the `rep` method:
pry(main)> cd Pry
pry(Pry)> ls -M --grep re
pry(Pry):1> ls -M --grep re
Pry#methods: re readline refresh rep repl repl_epilogue repl_prologue retrieve_line
pry(Pry):1> show-method rep -l
@ -257,9 +249,9 @@ Note that we can also view C methods (from Ruby Core) using the
RETURN_ENUMERATOR(ary, 0, 0);
result = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
rb_ary_push(result, rb_ary_elt(ary, i));
}
if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
rb_ary_push(result, rb_ary_elt(ary, i));
}
}
return result;
}

View file

@ -21,15 +21,6 @@ end
desc "Set up and run tests"
task :default => [:test]
unless [].respond_to? :shuffle!
class Array
def shuffle!
# TODO: fill this in if anyone cares
self
end
end
end
def run_specs paths
quiet = ENV['VERBOSE'] ? '' : '-q'
exec "bacon -Ispec -rubygems #{quiet} #{paths.join ' '}"
@ -42,7 +33,7 @@ task :test do
if explicit_list = ENV['run']
explicit_list.split(',')
else
Dir['spec/**/*_spec.rb'].shuffle!
(Dir['spec/**/*_spec.rb'] - Dir["spec/isolation/*_spec.rb"]).shuffle!
end
run_specs paths
end

View file

@ -12,7 +12,6 @@ require 'securerandom'
require 'forwardable'
class Pry
# The default hooks - display messages when beginning and ending Pry sessions.
DEFAULT_HOOKS = Pry::Hooks.new.add_hook(:before_session, :default) do |out, target, _pry_|
next if _pry_.quiet?
@ -20,9 +19,9 @@ class Pry
end
# The default print
DEFAULT_PRINT = proc do |output, value|
DEFAULT_PRINT = proc do |output, value, _pry_|
Pry::Pager.with_pager(output) do |pager|
pager.print "=> "
pager.print _pry_.config.output_prefix
Pry::ColorPrinter.pp(value, pager, Pry::Terminal.width! - 1)
end
end
@ -103,7 +102,7 @@ class Pry
else
# Otherwise, saves current binding stack as old stack and pops last
# binding out of binding stack (the old stack still has that binding).
_pry_.command_state["cd"] ||= OpenStruct.new # FIXME
_pry_.command_state["cd"] ||= Pry::Config.from_hash({}) # FIXME
_pry_.command_state['cd'].old_stack = _pry_.binding_stack.dup
_pry_.binding_stack.pop
end
@ -122,65 +121,6 @@ class Pry
# This is to keep from breaking under Rails 3.2 for people who are doing that
# IRB = Pry thing.
module ExtendCommandBundle; end
# class accessors
# define class attributes before pry library is required
# fix initialize step of Pry (#1037)
class << self
extend Forwardable
# convenience method
def self.delegate_accessors(delagatee, *names)
def_delegators delagatee, *names
def_delegators delagatee, *names.map { |v| "#{v}=" }
end
# Get/Set the Proc that defines extra Readline completions (on top
# of the ones defined for IRB).
# @return [Proc] The Proc that defines extra Readline completions (on top
# @example Add file names to completion list
# Pry.custom_completions = proc { Dir.entries('.') }
attr_accessor :custom_completions
# @return [Fixnum] The current input line.
attr_accessor :current_line
# @return [Array] The Array of evaluated expressions.
attr_accessor :line_buffer
# @return [String] The __FILE__ for the `eval()`. Should be "(pry)"
# by default.
attr_accessor :eval_path
# @return [OpenStruct] Return Pry's config object.
attr_accessor :config
# @return [History] Return Pry's line history object.
attr_accessor :history
# @return [Boolean] Whether Pry was activated from the command line.
attr_accessor :cli
# @return [Boolean] Whether Pry sessions are quiet by default.
attr_accessor :quiet
# @return [Exception, nil] The last pry internal error.
# (a CommandError in most cases)
attr_accessor :last_internal_error
# plugin forwardables
def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins
delegate_accessors :@config, :input, :output, :commands, :prompt, :print, :exception_handler,
:hooks, :color, :pager, :editor, :memory_size, :extra_sticky_locals
end
end
if Pry::Helpers::BaseHelpers.mri_18?
begin
require 'ruby18_source_location'
rescue LoadError
end
end
require 'method_source'
@ -192,23 +132,13 @@ require 'rbconfig'
require 'tempfile'
require 'pathname'
begin
begin
require 'readline'
rescue LoadError
require 'rb-readline'
end
rescue LoadError
warn "You're running a version of ruby with no Readline support"
warn "Please `gem install rb-readline` or recompile ruby --with-readline."
exit!
end
if Pry::Helpers::BaseHelpers.jruby?
begin
require 'ffi'
rescue LoadError
warn "Need to `gem install ffi`"
# TODO: Why do we need this?
warn "For a better Pry experience on JRuby, please `gem install ffi`."
end
end
@ -219,7 +149,8 @@ if Pry::Helpers::BaseHelpers.windows? && !Pry::Helpers::BaseHelpers.windows_ansi
# only fail on jruby (where win32console doesn't work).
# Instead we'll recommend ansicon, which does.
rescue LoadError
warn "For a better pry experience, please use ansicon: http://adoxa.3eeweb.com/ansicon/"
warn "For a better Pry experience on Windows, please use ansicon:"
warn " http://adoxa.3eeweb.com/ansicon/"
end
end
@ -241,7 +172,6 @@ require 'pry/history'
require 'pry/command'
require 'pry/command_set'
require 'pry/commands'
require 'pry/custom_completions'
require 'pry/completion'
require 'pry/plugins'
require 'pry/core_extensions'
@ -253,3 +183,4 @@ require 'pry/pager'
require 'pry/terminal'
require 'pry/editor'
require 'pry/rubygem'
require "pry/indent"

View file

@ -44,7 +44,7 @@ class Pry
end
# Add a block responsible for processing parsed options.
def process_options(&block)
def add_option_processor(&block)
self.option_processors ||= []
option_processors << block
@ -198,7 +198,7 @@ Copyright (c) 2013 John Mair (banisterfiend)
"Start the session in the specified context. Equivalent to `context.pry` in a session.",
:default => "Pry.toplevel_binding"
)
end.process_options do |opts|
end.add_option_processor do |opts|
exit if opts.help?

View file

@ -112,12 +112,6 @@ class Pry
end
def method_or_class_lookup
# we need this here because stupid Pry::Method.from_str() does a
# Pry::Method.from_binding when str is nil.
# Once we refactor Pry::Method.from_str() so it doesnt lookup
# from bindings, we can get rid of this check
return nil if str.to_s.empty?
obj = case str
when /\S+\(\)\z/
Pry::Method.from_str(str.sub(/\(\)\z/, ''),target) || Pry::WrappedModule.from_str(str, target)

View file

@ -37,8 +37,9 @@ class Pry
# Read the class name off of the singleton class to provide a default
# inspect.
eig = class << obj; self; end
klass = Pry::Method.safe_send(eig, :ancestors).first
singleton = class << obj; self; end
ancestors = Pry::Method.safe_send(singleton, :ancestors)
klass = ancestors.reject { |k| k == singleton }.first
obj_id = obj.__id__.to_s(16) rescue 0
str = "#<#{klass}:0x#{obj_id}>"

View file

@ -175,7 +175,7 @@ class Pry
end
def command_regex
pr = defined?(Pry.config.command_prefix) ? Pry.config.command_prefix : ""
pr = Pry.respond_to?(:config) ? Pry.config.command_prefix : ""
prefix = convert_to_regex(pr)
prefix = "(?:#{prefix})?" unless options[:use_prefix]
@ -194,6 +194,7 @@ class Pry
# The group in which the command should be displayed in "help" output.
# This is usually auto-generated from directory naming, but it can be
# manually overridden if necessary.
# Group should not be changed once it is initialized.
def group(name=nil)
@group ||= if name
name
@ -248,7 +249,7 @@ class Pry
end
def commands
command_set.commands
command_set.to_hash
end
def text
@ -284,7 +285,7 @@ class Pry
# state.my_state = "my state" # this will not conflict with any
# # `state.my_state` used in another command.
def state
_pry_.command_state[match] ||= OpenStruct.new
_pry_.command_state[match] ||= Pry::Config.from_hash({})
end
# Revaluate the string (str) and perform interpolation.

View file

@ -10,19 +10,15 @@ class Pry
class CommandSet
include Enumerable
include Pry::Helpers::BaseHelpers
attr_reader :commands
attr_reader :helper_module
# @param [Array<CommandSet>] imported_sets Sets which will be imported
# automatically
# @param [Array<Commandset>] imported_sets
# Sets which will be imported automatically
# @yield Optional block run to define commands
def initialize(*imported_sets, &block)
@commands = {}
@helper_module = Module.new
import(*imported_sets)
instance_eval(&block) if block
end
@ -83,7 +79,7 @@ class Pry
description, options = ["No description.", description] if description.is_a?(Hash)
options = Pry::Command.default_options(match).merge!(options)
commands[match] = Pry::BlockCommand.subclass(match, description, options, helper_module, &block)
@commands[match] = Pry::BlockCommand.subclass(match, description, options, helper_module, &block)
end
alias_method :command, :block_command
@ -115,9 +111,9 @@ class Pry
description, options = ["No description.", description] if description.is_a?(Hash)
options = Pry::Command.default_options(match).merge!(options)
commands[match] = Pry::ClassCommand.subclass(match, description, options, helper_module, &block)
commands[match].class_eval(&block)
commands[match]
@commands[match] = Pry::ClassCommand.subclass(match, description, options, helper_module, &block)
@commands[match].class_eval(&block)
@commands[match]
end
# Execute a block of code before a command is invoked. The block also
@ -157,7 +153,7 @@ class Pry
def delete(*searches)
searches.each do |search|
cmd = find_command_by_match_or_listing(search)
commands.delete cmd.match
@commands.delete cmd.match
end
end
@ -167,7 +163,7 @@ class Pry
# @return [Pry::CommandSet] Returns the reciever (a command set).
def import(*sets)
sets.each do |set|
commands.merge! set.commands
@commands.merge! set.to_hash
helper_module.send :include, set.helper_module
end
self
@ -181,7 +177,7 @@ class Pry
helper_module.send :include, set.helper_module
matches.each do |match|
cmd = set.find_command_by_match_or_listing(match)
commands[cmd.match] = cmd
@commands[cmd.match] = cmd
end
self
end
@ -190,8 +186,8 @@ class Pry
# of the command to retrieve.
# @return [Command] The command object matched.
def find_command_by_match_or_listing(match_or_listing)
cmd = (commands[match_or_listing] ||
Pry::Helpers::BaseHelpers.find_command(match_or_listing, commands))
cmd = (@commands[match_or_listing] ||
Pry::Helpers::BaseHelpers.find_command(match_or_listing, @commands))
cmd or raise ArgumentError, "Cannot find a command: '#{match_or_listing}'!"
end
@ -250,11 +246,11 @@ class Pry
:description => cmd.description
}.merge!(options)
commands[new_match] = cmd.dup
commands[new_match].match = new_match
commands[new_match].description = options.delete(:description)
commands[new_match].options.merge!(options)
commands.delete(cmd.match)
@commands[new_match] = cmd.dup
@commands[new_match].match = new_match
@commands[new_match].description = options.delete(:description)
@commands[new_match].options.merge!(options)
@commands.delete(cmd.match)
end
def disabled_command(name_of_disabled_command, message, matcher=name_of_disabled_command)
@ -303,16 +299,23 @@ class Pry
end
# @return [Array] The list of commands provided by the command set.
# @return [Array]
# The list of commands provided by the command set.
def list_commands
commands.keys
@commands.keys
end
alias_method :keys, :list_commands
def to_hash
@commands.dup
end
alias_method :to_h, :to_hash
# Find a command that matches the given line
# @param [String] val The line that might be a command invocation
# @return [Pry::Command, nil]
def [](pattern)
commands.values.select do |command|
@commands.values.select do |command|
command.matches?(pattern)
end.sort_by do |command|
command.match_score(pattern)
@ -337,7 +340,7 @@ class Pry
#
def []=(pattern, command)
if command.equal?(nil)
return commands.delete(pattern)
return @commands.delete(pattern)
end
unless Class === command && command < Pry::Command
raise TypeError, "command is not a subclass of Pry::Command"
@ -396,7 +399,7 @@ class Pry
# @private (used for testing)
def run_command(context, match, *args)
command = commands[match] or raise NoCommandError.new(match, self)
command = @commands[match] or raise NoCommandError.new(match, self)
command.new(context).call_safely(*args)
end
@ -408,7 +411,7 @@ class Pry
if command = find_command(search)
command.new(context).complete(search)
else
commands.keys.select do |key|
@commands.keys.select do |key|
String === key && key.start_with?(search)
end.map{ |key| key + " " } + Bond::DefaultMission.completions
end

View file

@ -1,9 +1,9 @@
class Pry
class Command::Cat
class ExceptionFormatter < AbstractFormatter
attr_accessor :ex
attr_accessor :opts
attr_accessor :_pry_
attr_reader :ex
attr_reader :opts
attr_reader :_pry_
def initialize(exception, _pry_, opts)
@ex = exception
@ -23,7 +23,7 @@ class Pry
private
def code_window_size
Pry.config.default_window_size || 5
_pry_.config.default_window_size || 5
end
def backtrace_level

View file

@ -1,9 +1,9 @@
class Pry
class Command::Cat
class FileFormatter < AbstractFormatter
attr_accessor :file_with_embedded_line
attr_accessor :opts
attr_accessor :_pry_
attr_reader :file_with_embedded_line
attr_reader :opts
attr_reader :_pry_
def initialize(file_with_embedded_line, _pry_, opts)
@file_with_embedded_line = file_with_embedded_line
@ -36,7 +36,7 @@ class Pry
end
def code_window_size
Pry.config.default_window_size || 7
_pry_.config.default_window_size || 7
end
def decorate(content)
@ -49,7 +49,7 @@ class Pry
def detect_code_type_from_file(file_name)
code_type = @code_from_file.code_type
if code_type == :unknown
name, ext = File.basename(file_name).split('.', 2)
case name

View file

@ -9,7 +9,7 @@ class Pry
Move into new context (object or scope). As in UNIX shells use `cd ..` to go
back, `cd /` to return to Pry top-level and `cd -` to toggle between last two
scopes. Complex syntax (e.g `cd ../@x/y`) also supported.
scopes. Complex syntax (e.g `cd ../@x/@y`) also supported.
cd @x
cd ..

View file

@ -2,9 +2,9 @@ class Pry
class Command::CodeCollector
include Helpers::CommandHelpers
attr_accessor :args
attr_accessor :opts
attr_accessor :_pry_
attr_reader :args
attr_reader :opts
attr_reader :_pry_
# The name of the explicitly given file (if any).
attr_accessor :file
@ -91,7 +91,7 @@ class Pry
# @return [String]
def pry_output_content
pry_array_content_as_string(_pry_.output_array, self.class.output_result_ranges) do |v|
Pry.config.gist.inspecter.call(v)
_pry_.config.gist.inspecter.call(v)
end
end

View file

@ -12,7 +12,7 @@ class Pry
Open a text editor. When no FILE is given, edits the pry input buffer.
When a method/module/command is given, the code is opened in an editor.
Ensure `Pry.config.editor` is set to your editor of choice.
Ensure `Pry.config.editor` or `_pry_.config.editor` is set to your editor of choice.
edit sample.rb edit -p MyClass#my_method
edit sample.rb --line 105 edit MyClass
@ -165,7 +165,7 @@ class Pry
end
def never_reload?
opts.present?(:'no-reload') || Pry.config.disable_auto_reload
opts.present?(:'no-reload') || _pry_.config.disable_auto_reload
end
def reload?(file_name="")
@ -186,7 +186,7 @@ class Pry
end
def probably_a_file?(str)
[".rb", ".c", ".py", ".yml", ".gemspec"].include? File.extname(str) ||
[".rb", ".c", ".py", ".yml", ".gemspec"].include?(File.extname(str)) ||
str =~ /\/|\\/
end

View file

@ -6,8 +6,6 @@ class Pry
group 'Context'
description 'Recursively search for a method within a Class/Module or the current namespace.'
command_options :shellwords => false
command_options :requires_gem => 'ruby18_source_location' if mri_18?
banner <<-'BANNER'
Usage: find-method [-n|-c] METHOD [NAMESPACE]
@ -26,10 +24,6 @@ class Pry
find-method -c 'output.puts' Pry
BANNER
def setup
require 'ruby18_source_location' if mri_18?
end
def options(opti)
opti.on :n, :name, "Search for a method by name"
opti.on :c, :content, "Search for a method based on content in Regex form"

View file

@ -58,7 +58,7 @@ class Pry
if code && code != ""
content << code
if code !~ /;\Z/
content << "#{comment_expression_result_for_gist(Pry.config.gist.inspecter.call(_pry_.output_array[corrected_index]))}"
content << "#{comment_expression_result_for_gist(_pry_.config.gist.inspecter.call(_pry_.output_array[corrected_index]))}"
end
end
end

View file

@ -29,7 +29,7 @@ class Pry
def options(opt)
opt.on :m, :methods, "Show public methods defined on the Object"
opt.on :M, "instance-methods", "Show methods defined in a Module or Class"
opt.on :M, "instance-methods", "Show public methods defined in a Module or Class"
opt.on :p, :ppp, "Show public, protected (in yellow) and private (in green) methods"
opt.on :q, :quiet, "Show only methods defined on object.singleton_class and object.class"
opt.on :v, :verbose, "Show methods and constants on all super-classes (ignores Pry.config.ls.ceiling)"
@ -59,11 +59,10 @@ class Pry
ls_entity = LsEntity.new({
:interrogatee => @interrogatee,
:target => target,
:no_user_opts => no_user_opts?,
:opts => opts,
:sticky_locals => _pry_.sticky_locals,
:args => args
:args => args,
:_pry_ => _pry_
})
stagger_output(ls_entity.entities_table)
@ -73,7 +72,7 @@ class Pry
def error_list
any_args = args.any?
non_mod_interrogatee = !Module === @interrogatee
non_mod_interrogatee = !(Module === @interrogatee)
[
['-l does not make sense with a specified Object', :locals, any_args],
['-g does not make sense with a specified Object', :globals, any_args],

View file

@ -1,13 +1,13 @@
require 'pry/commands/ls/interrogateable'
require 'pry/commands/ls/interrogatable'
class Pry
class Command::Ls < Pry::ClassCommand
class Constants < Pry::Command::Ls::Formatter
include Pry::Command::Ls::Interrogatable
include Pry::Command::Ls::Interrogateable
def initialize(interrogatee, target, no_user_opts, opts)
super(target)
def initialize(interrogatee, no_user_opts, opts, _pry_)
super(_pry_)
@interrogatee = interrogatee
@no_user_opts = no_user_opts
@default_switch = opts[:constants]

View file

@ -1,11 +1,12 @@
class Pry
class Command::Ls < Pry::ClassCommand
class Formatter
attr_accessor :grep
attr_reader :_pry_
def initialize(target)
@target = target
def initialize(_pry_)
@_pry_ = _pry_
@target = _pry_.current_context
end
def write_out
@ -16,7 +17,7 @@ class Pry
private
def color(type, str)
Pry::Helpers::Text.send(Pry.config.ls.send(:"#{type}_color"), str)
Pry::Helpers::Text.send _pry_.config.ls["#{type}_color"], str
end
# Add a new section to the output.

View file

@ -19,8 +19,8 @@ class Pry
$CHILD_STATUS $SAFE $ERROR_INFO $ERROR_POSITION $LAST_MATCH_INFO
$LAST_PAREN_MATCH $LAST_READ_LINE $MATCH $POSTMATCH $PREMATCH)
def initialize(target, opts)
super(target)
def initialize(opts, _pry_)
super(_pry_)
@default_switch = opts[:globals]
end
@ -32,7 +32,7 @@ class Pry
private
def format(globals)
globals.sort_by(&:downcase).map do |name|
globals.map(&:to_s).sort_by(&:downcase).map do |name|
if PSEUDO_GLOBALS.include?(name)
color(:pseudo_global, name)
elsif BUILTIN_GLOBALS.include?(name)

View file

@ -1,12 +1,12 @@
require 'pry/commands/ls/interrogateable'
require 'pry/commands/ls/interrogatable'
class Pry
class Command::Ls < Pry::ClassCommand
class InstanceVars < Pry::Command::Ls::Formatter
include Pry::Command::Ls::Interrogatable
include Pry::Command::Ls::Interrogateable
def initialize(interrogatee, no_user_opts, opts)
def initialize(interrogatee, no_user_opts, opts, _pry_)
super(_pry_)
@interrogatee = interrogatee
@no_user_opts = no_user_opts
@default_switch = opts[:ivars]

View file

@ -1,4 +1,4 @@
module Pry::Command::Ls::Interrogateable
module Pry::Command::Ls::Interrogatable
private
@ -10,9 +10,8 @@ module Pry::Command::Ls::Interrogateable
if interrogating_a_module?
@interrogatee
else
class << @interrogatee
ancestors.grep(::Class).reject { |c| c == self }.first
end
singleton = Pry::Method.singleton_class_of(@interrogatee)
singleton.ancestors.grep(::Class).reject { |c| c == singleton }.first
end
end

View file

@ -2,11 +2,11 @@ class Pry
class Command::Ls < Pry::ClassCommand
class LocalNames < Pry::Command::Ls::Formatter
def initialize(target, no_user_opts, sticky_locals, args)
super(target)
def initialize(no_user_opts, args, _pry_)
super(_pry_)
@no_user_opts = no_user_opts
@sticky_locals = sticky_locals
@args = args
@sticky_locals = _pry_.sticky_locals
end
def correct_opts?

View file

@ -2,10 +2,10 @@ class Pry
class Command::Ls < Pry::ClassCommand
class LocalVars < Pry::Command::Ls::Formatter
def initialize(target, sticky_locals, opts)
super(target)
@sticky_locals = sticky_locals
def initialize(opts, _pry_)
super(_pry_)
@default_switch = opts[:locals]
@sticky_locals = _pry_.sticky_locals
end
def output_self

View file

@ -12,15 +12,15 @@ class Pry
class Command::Ls < Pry::ClassCommand
class LsEntity
attr_reader :_pry_
def initialize(opts)
@interrogatee = opts[:interrogatee]
@target = opts[:target]
@no_user_opts = opts[:no_user_opts]
@opts = opts[:opts]
@sticky_locals = opts[:sticky_locals]
@args = opts[:args]
@grep = Grep.new(Regexp.new(opts[:opts][:G] || '.'))
@_pry_ = opts.delete(:_pry_)
end
def entities_table
@ -29,45 +29,42 @@ class Pry
private
def greppable
proc do |entity|
entity.tap { |o| o.grep = @grep }
end
def grep(entity)
entity.tap { |o| o.grep = @grep }
end
def globals
greppable.call(Globals.new(@target, @opts))
grep Globals.new(@opts, _pry_)
end
def constants
greppable.call(Constants.new(@interrogatee, @target, @no_user_opts, @opts))
grep Constants.new(@interrogatee, @no_user_opts, @opts, _pry_)
end
def methods
greppable.call(Methods.new(@interrogatee, @no_user_opts, @opts))
grep(Methods.new(@interrogatee, @no_user_opts, @opts, _pry_))
end
def self_methods
greppable.call(SelfMethods.new(@interrogatee, @no_user_opts, @opts))
grep SelfMethods.new(@interrogatee, @no_user_opts, @opts, _pry_)
end
def instance_vars
greppable.call(InstanceVars.new(@interrogatee, @no_user_opts, @opts))
grep InstanceVars.new(@interrogatee, @no_user_opts, @opts, _pry_)
end
def local_names
greppable.call(LocalNames.new(@target, @no_user_opts, @sticky_locals, @args))
grep LocalNames.new(@no_user_opts, @args, _pry_)
end
def local_vars
LocalVars.new(@target, @sticky_locals, @opts)
LocalVars.new(@opts, _pry_)
end
def entities
[globals, constants, methods, self_methods, instance_vars, local_names,
local_vars]
end
end
end
end

View file

@ -1,14 +1,15 @@
require 'pry/commands/ls/methods_helper'
require 'pry/commands/ls/interrogateable'
require 'pry/commands/ls/interrogatable'
class Pry
class Command::Ls < Pry::ClassCommand
class Methods < Pry::Command::Ls::Formatter
include Pry::Command::Ls::Interrogateable
include Pry::Command::Ls::Interrogatable
include Pry::Command::Ls::MethodsHelper
def initialize(interrogatee, no_user_opts, opts)
def initialize(interrogatee, no_user_opts, opts, _pry_)
super(_pry_)
@interrogatee = interrogatee
@no_user_opts = no_user_opts
@default_switch = opts[:methods]
@ -42,11 +43,11 @@ class Pry
def below_ceiling
ceiling = if @quiet_switch
[Pry::Method.safe_send(interrogatee_mod, :ancestors)[1]] +
Pry.config.ls.ceiling
_pry_.config.ls.ceiling
elsif @verbose_switch
[]
else
Pry.config.ls.ceiling.dup
_pry_.config.ls.ceiling.dup
end
lambda { |klass| !ceiling.include?(klass) }
end

View file

@ -1,14 +1,14 @@
require 'pry/commands/ls/interrogateable'
require 'pry/commands/ls/interrogatable'
require 'pry/commands/ls/methods_helper'
class Pry
class Command::Ls < Pry::ClassCommand
class SelfMethods < Pry::Command::Ls::Formatter
include Pry::Command::Ls::Interrogateable
include Pry::Command::Ls::Interrogatable
include Pry::Command::Ls::MethodsHelper
def initialize(interrogatee, no_user_opts, opts)
def initialize(interrogatee, no_user_opts, opts, _pry_)
super(_pry_)
@interrogatee = interrogatee
@no_user_opts = no_user_opts
end

View file

@ -20,11 +20,10 @@ class Pry
process_cd parse_destination($1)
else
pass_block(cmd)
if command_block
command_block.call `#{cmd}`
else
Pry.config.system.call(output, cmd, _pry_)
_pry_.config.system.call(output, cmd, _pry_)
end
end
end

View file

@ -12,10 +12,10 @@ class Pry
case _pry_.prompt
when Pry::SHELL_PROMPT
_pry_.pop_prompt
_pry_.custom_completions = Pry::DEFAULT_CUSTOM_COMPLETIONS
_pry_.custom_completions = _pry_.config.file_completions
else
_pry_.push_prompt Pry::SHELL_PROMPT
_pry_.custom_completions = Pry::FILE_COMPLETIONS
_pry_.custom_completions = _pry_.config.command_completions
end
end
end

View file

@ -3,11 +3,6 @@ class Pry
extend Pry::Helpers::BaseHelpers
command_options :shellwords => false, :interpolate => false
command_options :requires_gem => "ruby18_source_location" if mri_18?
def setup
require 'ruby18_source_location' if mri_18?
end
def options(opt)
opt.on :s, :super, "Select the 'super' method. Can be repeated to traverse the ancestors", :as => :count

View file

@ -0,0 +1,105 @@
class Pry
class Command::WatchExpression < Pry::ClassCommand
require 'pry/commands/watch_expression/expression.rb'
match 'watch'
group 'Context'
description 'Watch the value of an expression and print a notification whenever it changes.'
command_options :use_prefix => false
banner <<-'BANNER'
Usage: watch [EXPRESSION]
watch
watch --delete [INDEX]
watch [EXPRESSION] adds an expression to the list of those being watched.
It will be re-evaluated every time you hit enter in pry. If its value has
changed, the new value will be printed to the console.
This is useful if you are step-through debugging and want to see how
something changes over time. It's also useful if you're trying to write
a method inside pry and want to check that it gives the right answers
every time you redefine it.
watch on its own displays all the currently watched expressions and their
values, and watch --delete [INDEX] allows you to delete expressions from
the list being watched.
BANNER
def options(opt)
opt.on :d, :delete,
"Delete the watch expression with the given index. If no index is given; clear all watch expressions.",
:optional_argument => true, :as => Integer
opt.on :l, :list,
"Show all current watch expressions and their values. Calling watch with no expressions or options will also show the watch expressions."
end
def process
case
when opts.present?(:delete)
delete opts[:delete]
when opts.present?(:list) || args.empty?
list
else
add_hook
add_expression(args)
end
end
private
def expressions
_pry_.config.watch_expressions ||= []
end
def delete(index)
if index
output.puts "Deleting watch expression ##{index}: #{expressions[index-1]}"
expressions.delete_at(index-1)
else
output.puts "Deleting all watched expressions"
expressions.clear
end
end
def list
if expressions.empty?
output.puts "No watched expressions"
else
Pry::Pager.with_pager(output) do |pager|
pager.puts "Listing all watched expressions:"
pager.puts ""
expressions.each_with_index do |expr, index|
pager.print text.with_line_numbers(expr.to_s, index+1)
end
pager.puts ""
end
end
end
def eval_and_print_changed(output)
expressions.each do |expr|
expr.eval!
if expr.changed?
output.puts "#{text.blue "watch"}: #{expr.to_s}"
end
end
end
def add_expression(arguments)
expressions << Expression.new(target, arg_string)
output.puts "Watching #{Code.new(arg_string)}"
end
def add_hook
hook = [:after_eval, :watch_expression]
unless _pry_.hooks.hook_exists?(*hook)
_pry_.hooks.add_hook(*hook) do |_, _pry_|
eval_and_print_changed _pry_.output
end
end
end
end
Pry::Commands.add_command(Pry::Command::WatchExpression)
end

View file

@ -0,0 +1,37 @@
class Pry
class Command::WatchExpression
class Expression
attr_reader :target, :source, :value, :previous_value
def initialize(target, source)
@target = target
@source = Code.new(source).strip
end
def eval!
@previous_value = @value
@value = Pry::ColorPrinter.pp(target_eval(target, source), "")
end
def to_s
"#{source} => #{value}"
end
# Has the value of the expression changed?
#
# We use the pretty-printed string represenation to detect differences
# as this avoids problems with dup (causes too many differences) and == (causes too few)
def changed?
(value != previous_value)
end
private
def target_eval(target, source)
target.eval(source)
rescue => e
e
end
end
end
end

View file

@ -109,7 +109,7 @@ class Pry
end
def top_level?
target_self == TOPLEVEL_BINDING.eval("self")
target_self == Pry.main
end
def handle_internal_binding
@ -178,7 +178,7 @@ class Pry
def window_size
if args.empty?
Pry.config.default_window_size
_pry_.config.default_window_size
else
args.first.to_i
end

View file

@ -1,260 +1,24 @@
require 'ostruct'
class Pry::Config
require_relative 'config/behavior'
require_relative 'config/default'
require_relative 'config/convenience'
include Pry::Config::Behavior
class Pry
class Config < OpenStruct
def self.shortcuts
Convenience::SHORTCUTS
end
# Get/Set the object to use for input by default by all Pry instances.
# Pry.config.input is an option determining the input object - the object
# from which Pry retrieves its lines of input. Pry accepts any object that
# implements the readline method. This includes IO objects, StringIO,
# Readline, File and custom objects.
# @return [#readline] The object to use for input by default by all
# Pry instances.
# @example
# Pry.config.input = StringIO.new("@x = 10\nexit")
attr_accessor :input
# Get/Set the object to use for output by default by all Pry instances.
# Pry.config.output is an option determining the output object - the object
# to which Pry writes its output. Pry accepts any object that implements the
# puts method. This includes IO objects, StringIO, File and custom objects.
# @return [#puts] The object to use for output by default by all
# Pry instances.
# @example
# Pry.config.output = StringIO.new
attr_accessor :output
# Get/Set the object to use for commands by default by all Pry instances.
# @return [Pry::CommandBase] The object to use for commands by default by
# all Pry instances.
# @example
# Pry.config.commands = Pry::CommandSet.new do
# import_from Pry::Commands, "ls"
# command "greet" do |name|
# output.puts "hello #{name}"
# end
# end
attr_accessor :commands
# Get/Set the Proc to use for printing by default by all Pry
# instances.
# Two parameters are passed to the print Proc: these are (1) the
# output object for the current session and (2) the expression value to
# print. It is important that you write to the output object instead of just
# stdout so that all Pry output can be redirected if necessary. This is the
# 'print' component of the REPL.
# @return [Proc] The Proc to use for printing by default by all
# Pry instances.
# @example
# Pry.config.print = proc { |output, value| output.puts "=> #{value.inspect}" }
attr_accessor :print
# Pry.config.exception_handler is an option determining the exception
# handler object - the Proc responsible for dealing with exceptions raised
# by user input to the REPL. Three parameters are passed to the exception
# handler Proc: these are (1) the output object for the current session, (2)
# the exception object that was raised inside the Pry session, and (3) a
# reference to the associated Pry instance.
# @return [Proc] The Proc to use for printing exceptions by default by all
# Pry instances.
# @example
# Pry.config.exception_handler = proc do |output, exception, _|
# output.puts "#{exception.class}: #{exception.message}"
# output.puts "from #{exception.backtrace.first}"
# end
attr_accessor :exception_handler
# @return [Array] The classes of exception that will not be caught by Pry.
# @example
# Pry.config.exception_whitelist = [SystemExit, SignalException]
attr_accessor :exception_whitelist
# Send Pry into interactive mode after finishing execution
# @return [Boolean]
attr_accessor :exit_interactive
# @return [Fixnum] The number of lines of context to show before and after
# exceptions, etc.
# @example
# Pry.config.default_window_size = 10
attr_accessor :default_window_size
# Get/Set the `Pry::Hooks` instance that defines Pry hooks used by default
# by all Pry instances.
# @return [Pry::Hooks] The hooks used by default by all Pry instances.
# @example
# Pry.config.hooks = Pry::Hooks.new.add_hook(:before_session,
# :default) { |output, target, _pry_| output.puts "Good morning!" }
attr_reader :hooks
# FIXME:
# This is a hack to alert people of the new API.
# @param [Pry::Hooks] v Only accept `Pry::Hooks` now!
def hooks=(v)
if v.is_a?(Hash)
warn "Hash-based hooks are now deprecated! Use a `Pry::Hooks` object instead! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"
@hooks = Pry::Hooks.from_hash(v)
else
@hooks = v
end
#
# FIXME
# @param [Pry::Hooks] hooks
#
def hooks=(hooks)
if hooks.is_a?(Hash)
warn "Hash-based hooks are now deprecated! Use a `Pry::Hooks` object " \
"instead! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"
self["hooks"] = Pry::Hooks.from_hash(hooks)
else
self["hooks"] = hooks
end
# Get the array of Procs (or single Proc) to be used for the prompts by
# default by all Pry instances. Three parameters are passed into the prompt
# procs, (1) the object that is the target of the session, (2) the current
# nesting level, and (3) a reference to the associated Pry instance. These
# objects can be used in the prompt, if desired.
# @return [Array<Proc>, Proc] The array of Procs to be used for the
# prompts by default by all Pry instances.
# @example
# Pry.config.prompt = proc { |obj, nest_level, _pry_| "#{obj}:#{nest_level}> " }
attr_accessor :prompt
# The display name that is part of the prompt. Default is 'pry'. You can
# set your own name so you can identify which project your current pry
# session is using. This is useful if you have a local pryrc file in a
# Rails project for example.
# @return [String]
# @example
# Pry.config.prompt_name = 'my_rails_project'
attr_accessor :prompt_name
# The list of safe objects, the `#inspect` method of which can be used for
# the prompt. The default safe objects are defined in
# `DEFAULT_PROMPT_SAFE_OBJECTS` (see Pry::DEFAULT_PROMPT_SAFE_OBJECTS).
# @return [Array]
# @example
# class Barbie
# def inspect
# 'You can brush my hair, undress me everywhere!'
# end
# end
#
# Pry.config.prompt_safe_objects << Barbie
attr_accessor :prompt_safe_objects
# The default editor to use. Defaults to $VISUAL, $EDITOR, or a sensible
# fallback for the platform. If `editor` is a String then that string is
# used as the shell command to invoke the editor. If `editor` is callable
# (e.g a Proc) then `file`, `line`, and `reloading` are passed in as
# parameters and the return value of that callable invocation is used as the
# exact shell command to invoke the editor. `reloading` indicates whether
# Pry will be reloading code after the shell command returns. Any or all of
# these parameters can be omitted from the callable's signature.
# @example String
# Pry.config.editor = "emacsclient"
# @example Callable
# Pry.config.editor = proc { |file, line| "emacsclient #{file} +#{line}" }
# @example Callable waiting only if reloading
# Pry.config.editor = proc { |file, line, reloading|
# "subl #{'--wait' if reloading} #{file}:#{line}"
# }
# @return [String, #call]
attr_accessor :editor
# A string that must precede all Pry commands (e.g., if command_prefix is
# set to "%", the "cd" command must be invoked as "%cd").
# @return [String]
attr_accessor :command_prefix
# @return [Boolean] Toggle Pry color on and off.
attr_accessor :color
# @return [Boolean] Toggle paging on and off.
attr_accessor :pager
# Determines whether the rc file (~/.pryrc) should be loaded.
# @return [Boolean]
attr_accessor :should_load_rc
# Determines whether the local rc file (./.pryrc) should be loaded.
# @return [Boolean]
attr_accessor :should_load_local_rc
# Determines whether plugins should be loaded.
# @return [Boolean]
attr_accessor :should_load_plugins
# Determines whether to load files specified with the -r flag.
# @return [Boolean]
attr_accessor :should_load_requires
# Determines whether to disable edit-method's auto-reloading behavior.
# @return [Boolean]
attr_accessor :disable_auto_reload
# Determines whether Pry should trap SIGINT and cause it to raise an
# Interrupt exception. This is only useful on jruby, MRI does this
# for us.
# @return [Boolean]
attr_accessor :should_trap_interrupts
# Config option for history.
# sub-options include history.file, history.load, and history.save
# history.file is the file to save/load history to, e.g
# Pry.config.history.file = "~/.pry_history".
# history.should_load is a boolean that determines whether history will be
# loaded from history.file at session start.
# history.should_save is a boolean that determines whether history will be
# saved to history.file at session end.
# @return [OpenStruct]
attr_accessor :history
# Config option for plugins:
# sub-options include:
# `plugins.strict_loading` (Boolean) which toggles whether referring to a
# non-existent plugin should raise an exception (defaults to `false`).
# @return [OpenStruct]
attr_accessor :plugins
# @return [Array<String>] Ruby files to be required after loading
# any plugins.
attr_accessor :requires
# @return [Integer] Amount of results that will be stored into out
attr_accessor :memory_size
# @return [Proc] The proc that manages ^D presses in the REPL.
# The proc is passed the current eval_string and the current pry instance.
attr_accessor :control_d_handler
# @return [Proc] The proc that runs system commands
# The proc is passed the pry output object, the command string
# to eval, and a reference to the pry instance
attr_accessor :system
# @return [Boolean] Whether or not code should be indented
# using Pry::Indent.
attr_accessor :auto_indent
# @return [Boolean] Whether or not indentation should be corrected
# after hitting enter. This feature is not supported by all terminals.
attr_accessor :correct_indent
# @return [Boolean] Whether or not a warning will be displayed when
# a command name collides with a method/local in the current context.
attr_accessor :collision_warning
# Config option for gist.
# sub-options include `gist.inspecter`,
# `gist.inspecter` is a callable that defines how the expression output
# will be displayed when using the `gist -i` command.
# @example Pretty inspect output
# Pry.config.gist.inspecter = proc { |v| v.pretty_inspect }
# @example Regular inspect
# Pry.config.gist.inspecter = proc &:inspect
# @return [OpenStruct]
attr_accessor :gist
# @return [Hash] Additional sticky locals (to the standard ones) to use in
# Pry sessions.
# @example Inject `random_number` sticky local into Pry session
# Pry.config.extra_sticky_locals = { :random_number => proc {
# rand(10) } }
attr_accessor :extra_sticky_locals
# @return [#build_completion_proc] A completer to use.
attr_accessor :completer
end
end

115
lib/pry/config/behavior.rb Normal file
View file

@ -0,0 +1,115 @@
module Pry::Config::Behavior
ASSIGNMENT = "=".freeze
NODUP = [TrueClass, FalseClass, NilClass, Symbol, Numeric, Module, Proc].freeze
RESERVED_KEYS = [
"[]", "[]=", "merge!",
"respond_to?", "key?", "refresh",
"forget", "inherited_by", "to_h",
"to_hash", "_dup"
].freeze
def self.included(klass)
klass.extend Module.new {
def from_hash(hash, default = nil)
new(default).tap do |config|
config.merge!(hash)
end
end
}
end
def initialize(default = Pry.config)
@default = default.dup if default
@default.inherited_by(self) if default
@writes = {}
end
def [](key)
@writes[key.to_s]
end
def []=(key, value)
key = key.to_s
if RESERVED_KEYS.include?(key)
raise ArgumentError, "sorry, '#{key}' is a reserved configuration key."
end
@writes[key] = value
end
def method_missing(name, *args, &block)
key = name.to_s
if key[-1] == ASSIGNMENT
short_key = key[0..-2]
self[short_key] = args[0]
elsif key?(key)
self[key]
elsif @default.respond_to?(name)
value = @default.public_send(name, *args, &block)
self[key] = _dup(value)
else
nil
end
end
def merge!(other)
raise TypeError, "cannot coerce argument to Hash" unless other.respond_to?(:to_hash)
other = other.to_hash
other.each do |key, value|
self[key] = value
end
end
def respond_to?(name, boolean=false)
key?(name) or @default.respond_to?(name) or super(name, boolean)
end
def key?(key)
key = key.to_s
@writes.key?(key)
end
def refresh
@writes.clear
true
end
def forget(key)
@writes.delete(key.to_s)
end
def inherited_by(other)
if @inherited_by
raise RuntimeError, "instance of '#{self.class}' cannot reassign its child."
else
@inherited_by = other
end
end
def ==(other)
return false unless other.respond_to?(:to_hash)
to_hash == other.to_hash
end
alias_method :eql?, :==
def keys
@writes.keys
end
def to_hash
@writes.dup
end
alias_method :to_h, :to_hash
def quiet?
quiet
end
private
def _dup(value)
if NODUP.any? { |klass| klass === value }
value
else
value.dup
end
end
end

View file

@ -0,0 +1,26 @@
module Pry::Config::Convenience
SHORTCUTS = [
:input,
:output,
:commands,
:print,
:exception_handler,
:quiet?,
:hooks,
:color,
:pager,
:editor,
:memory_size,
:extra_sticky_locals
]
def config_shortcut(*names)
names.each do |name|
reader = name
setter = "#{name}="
define_method(reader) { config.public_send(name) }
define_method(setter) { |value| config.public_send(setter, value) }
end
end
end

123
lib/pry/config/default.rb Normal file
View file

@ -0,0 +1,123 @@
class Pry::Config::Default
include Pry::Config::Behavior
default = {
:input => proc { lazy_readline },
:output => proc { $stdout },
:commands => proc { Pry::Commands },
:prompt_name => proc { Pry::DEFAULT_PROMPT_NAME },
:prompt => proc { Pry::DEFAULT_PROMPT },
:prompt_safe_objects => proc { Pry::DEFAULT_PROMPT_SAFE_OBJECTS },
:print => proc { Pry::DEFAULT_PRINT },
:quiet => proc { false },
:exception_handler => proc { Pry::DEFAULT_EXCEPTION_HANDLER },
:exception_whitelist => proc { Pry::DEFAULT_EXCEPTION_WHITELIST },
:hooks => proc { Pry::DEFAULT_HOOKS },
:pager => proc { true },
:system => proc { Pry::DEFAULT_SYSTEM },
:color => proc { Pry::Helpers::BaseHelpers.use_ansi_codes? },
:default_window_size => proc { 5 },
:editor => proc { Pry.default_editor_for_platform }, # TODO: Pry::Platform.editor
:should_load_rc => proc { true },
:should_load_local_rc => proc { true },
:should_trap_interrupts => proc { Pry::Helpers::BaseHelpers.jruby? }, # TODO: Pry::Platform.jruby?
:disable_auto_reload => proc { false },
:command_prefix => proc { "" },
:auto_indent => proc { Pry::Helpers::BaseHelpers.use_ansi_codes? },
:correct_indent => proc { true },
:collision_warning => proc { false },
:output_prefix => proc { "=> "},
:requires => proc { [] },
:should_load_requires => proc { true },
:should_load_plugins => proc { true },
:control_d_handler => proc { Pry::DEFAULT_CONTROL_D_HANDLER },
:memory_size => proc { 100 },
:extra_sticky_locals => proc { {} },
:command_completions => proc { proc { commands.keys } },
:file_completions => proc { proc { Dir["."] } },
:completer => proc { lazy_completer }
}
def initialize
super(nil)
configure_ls
configure_gist
configure_history
end
default.each do |key, value|
define_method(key) do
if default[key].equal?(value)
default[key] = instance_eval(&value)
end
default[key]
end
end
private
# TODO:
# all of this configure_* stuff is a relic of old code.
# we should try move this code to being command-local.
def configure_ls
self["ls"] = Pry::Config.from_hash({
:heading_color => :bright_blue,
:public_method_color => :default,
:private_method_color => :blue,
:protected_method_color => :blue,
:method_missing_color => :bright_red,
:local_var_color => :yellow,
:pry_var_color => :default, # e.g. _, _pry_, _file_
:instance_var_color => :blue, # e.g. @foo
:class_var_color => :bright_blue, # e.g. @@foo
:global_var_color => :default, # e.g. $CODERAY_DEBUG, $eventmachine_library
:builtin_global_color => :cyan, # e.g. $stdin, $-w, $PID
:pseudo_global_color => :cyan, # e.g. $~, $1..$9, $LAST_MATCH_INFO
:constant_color => :default, # e.g. VERSION, ARGF
:class_constant_color => :blue, # e.g. Object, Kernel
:exception_constant_color => :magenta, # e.g. Exception, RuntimeError
:unloaded_constant_color => :yellow, # Any constant that is still in .autoload? state
:separator => " ",
:ceiling => [Object, Module, Class]
})
end
def configure_gist
self["gist"] = Pry::Config.from_hash(inspecter: proc(&:pretty_inspect))
end
def configure_history
self["history"] = Pry::Config.from_hash "should_save" => true,
"should_load" => true
history.file = File.expand_path("~/.pry_history") rescue nil
if history.file.nil?
self.should_load_rc = false
history.should_save = false
history.should_load = false
end
end
def lazy_readline
require 'readline'
Readline
rescue LoadError
warn "Sorry, you can't use Pry without Readline or a compatible library."
warn "Possible solutions:"
warn " * Rebuild Ruby with Readline support using `--with-readline`"
warn " * Use the rb-readline gem, which is a pure-Ruby port of Readline"
warn " * Use the pry-coolline gem, a pure-ruby alternative to Readline"
raise
end
def lazy_completer
if defined?(Bond) && !is_editline?(input)
Pry::BondCompleter.start
else
Pry::InputCompleter.start
end
end
def is_editline?(input)
defined?(input::VERSION) && input::VERSION =~ /editline/i
end
end

View file

@ -99,37 +99,33 @@ class Object
end
end
if defined?(BasicObject)
class BasicObject
# Return a binding object for the receiver.
#
# The `self` of the binding is set to the current object, and it contains no
# local variables.
#
# The default definee (http://yugui.jp/articles/846) is set such that new
# methods defined will be added to the singleton class of the BasicObject.
#
# @return [Binding]
def __binding__
# BasicObjects don't have respond_to?, so we just define the method
# every time. As they also don't have `.freeze`, this call won't
# fail as it can for normal Objects.
(class << self; self; end).class_eval <<-EOF, __FILE__, __LINE__ + 1
# Get a binding with 'self' set to self, and no locals.
#
# The default definee is determined by the context in which the
# definition is eval'd.
#
# Please don't call this method directly, see {__binding__}.
#
# @return [Binding]
def __pry__
# In ruby-1.8.7 ::Kernel.binding sets self to Kernel in the returned binding.
# Luckily ruby-1.8.7 doesn't have BasicObject, so this is safe.
::Kernel.binding
end
EOF
self.__pry__
end
class BasicObject
# Return a binding object for the receiver.
#
# The `self` of the binding is set to the current object, and it contains no
# local variables.
#
# The default definee (http://yugui.jp/articles/846) is set such that new
# methods defined will be added to the singleton class of the BasicObject.
#
# @return [Binding]
def __binding__
# BasicObjects don't have respond_to?, so we just define the method
# every time. As they also don't have `.freeze`, this call won't
# fail as it can for normal Objects.
(class << self; self; end).class_eval <<-EOF, __FILE__, __LINE__ + 1
# Get a binding with 'self' set to self, and no locals.
#
# The default definee is determined by the context in which the
# definition is eval'd.
#
# Please don't call this method directly, see {__binding__}.
#
# @return [Binding]
def __pry__
::Kernel.binding
end
EOF
self.__pry__
end
end

View file

@ -1,6 +0,0 @@
class Pry
# This proc will be instance_eval's against the active Pry instance
DEFAULT_CUSTOM_COMPLETIONS = proc { commands.commands.keys }
FILE_COMPLETIONS = proc { commands.commands.keys + Dir.entries('.') }
end

View file

@ -90,10 +90,6 @@ class Pry
RbConfig::CONFIG['ruby_install_name'] == 'ruby'
end
def mri_18?
mri? && RUBY_VERSION =~ /1.8/
end
def mri_19?
mri? && RUBY_VERSION =~ /1.9/
end

View file

@ -16,10 +16,18 @@ class Pry
# Assign the default methods for loading, saving, pushing, and clearing.
def restore_default_behavior
@loader = method(:read_from_file)
@saver = method(:save_to_file)
@pusher = method(:push_to_readline)
@clearer = method(:clear_readline)
Pry.config.input # force Readline to load if applicable
@loader = method(:read_from_file)
@saver = method(:save_to_file)
if defined?(Readline)
@pusher = method(:push_to_readline)
@clearer = method(:clear_readline)
else
@pusher = proc { }
@clearer = proc { }
end
end
# Load the input history using `History.loader`.

View file

@ -18,11 +18,11 @@ class Pry
# @param [Hash] hash The hash to convert to `Pry::Hooks`.
# @return [Pry::Hooks] The resulting `Pry::Hooks` instance.
def self.from_hash(hash)
return hash if hash.instance_of?(self)
instance = new
hash.each do |k, v|
instance.add_hook(k, nil, v)
end
instance
end
@ -146,18 +146,14 @@ class Pry
def exec_hook(event_name, *args, &block)
@hooks[event_name] ||= []
# silence warnings to get rid of 1.8's "warning: multiple values
# for a block parameter" warnings
Pry::Helpers::BaseHelpers.silence_warnings do
@hooks[event_name].map do |hook_name, callable|
begin
callable.call(*args, &block)
rescue RescuableException => e
errors << e
e
end
end.last
end
@hooks[event_name].map do |hook_name, callable|
begin
callable.call(*args, &block)
rescue RescuableException => e
errors << e
e
end
end.last
end
# Return the number of hook functions registered for the `event_name` event.

View file

@ -31,8 +31,7 @@ class Pry
# search in, find and return the requested method wrapped in a `Pry::Method`
# instance.
#
# @param [String, nil] name The name of the method to retrieve, or `nil` to
# delegate to `from_binding` instead.
# @param [String] name The name of the method to retrieve.
# @param [Binding] target The context in which to search for the method.
# @param [Hash] options
# @option options [Boolean] :instance Look for an instance method if `name` doesn't
@ -40,10 +39,10 @@ class Pry
# @option options [Boolean] :methods Look for a bound/singleton method if `name` doesn't
# contain any context.
# @return [Pry::Method, nil] A `Pry::Method` instance containing the requested
# method, or `nil` if no method could be located matching the parameters.
# method, or `nil` if name is `nil` or no method could be located matching the parameters.
def from_str(name, target=TOPLEVEL_BINDING, options={})
if name.nil?
from_binding(target)
nil
elsif name.to_s =~ /(.+)\#(\S+)\Z/
context, meth_name = $1, $2
from_module(target.eval(context), meth_name, target)
@ -154,7 +153,7 @@ class Pry
# @param [Boolean] include_super Whether to include methods from ancestors.
# @return [Array[Pry::Method]]
def all_from_obj(obj, include_super=true)
all_from_class(class << obj; self; end, include_super)
all_from_class(singleton_class_of(obj), include_super)
end
# Get every `Class` and `Module`, in order, that will be checked when looking
@ -193,8 +192,6 @@ class Pry
/^define_method\(?\s*[:\"\']#{Regexp.escape(name)}|^def\s*#{Regexp.escape(name)}/ =~ definition_line.strip
end
private
# Get the singleton classes of superclasses that could define methods on
# the given class object, and any modules they include.
# If a module is included at multiple points in the ancestry, only
@ -208,7 +205,13 @@ class Pry
resolution_order.reverse.uniq.reverse - Class.included_modules
end
def singleton_class_of(obj); class << obj; self; end end
def singleton_class_of(obj)
begin
class << obj; self; end
rescue TypeError # can't define singleton. Fixnum, Symbol, Float, ...
obj.class
end
end
end
# A new instance of `Pry::Method` wrapping the given `::Method`, `UnboundMethod`, or `Proc`.
@ -405,8 +408,6 @@ class Pry
end
# @return [Array<String>] All known aliases for the method.
# @note On Ruby 1.8 this method always returns an empty Array for methods
# implemented in C.
def aliases
owner = @method.owner
# Avoid using `to_sym` on {Method#name}, which returns a `String`, because

View file

@ -97,7 +97,7 @@ module Pry::Pager
@out.print "\e[0m" if Pry.color
@out.print "<page break> --- Press enter to continue " \
"( q<enter> to break ) --- <page break>\n"
raise StopPaging if Readline.readline.chomp == "q"
raise StopPaging if Readline.readline("").chomp == "q"
@tracker.reset
end
end

View file

@ -43,7 +43,7 @@ class Pry
# Does not reload plugin if it's already active.
def activate!
# Create the configuration object for the plugin.
Pry.config.send("#{gem_name.gsub('-', '_')}=", OpenStruct.new)
Pry.config.send("#{gem_name.gsub('-', '_')}=", Pry::Config.from_hash({}))
begin
require gem_name if !active?

View file

@ -1,15 +1,49 @@
require 'ostruct'
require 'pry/config'
class Pry
# The RC Files to load.
HOME_RC_FILE = ENV["PRYRC"] || "~/.pryrc"
LOCAL_RC_FILE = "./.pryrc"
# @return [Hash] Pry's `Thread.current` hash
class << self
extend Forwardable
attr_accessor :custom_completions
attr_accessor :current_line
attr_accessor :line_buffer
attr_accessor :eval_path
attr_accessor :cli
attr_accessor :quiet
attr_accessor :last_internal_error
attr_accessor :config
attr_writer :history
def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins
extend Pry::Config::Convenience
config_shortcut *Pry::Config.shortcuts
def prompt=(value)
config.prompt = value
end
def prompt
config.prompt
end
def history
@history ||= History.new
end
end
def self.main
@main ||= TOPLEVEL_BINDING.eval "self"
end
#
# @return [Pry::Config]
# Returns a value store for an instance of Pry running on the current thread.
#
def self.current
Thread.current[:__pry__] ||= {}
Thread.current[:__pry__] ||= Pry::Config.from_hash({}, nil)
end
# Load the given file in the context of `Pry.toplevel_binding`
@ -24,7 +58,9 @@ class Pry
# This method can also be used to reload the files if they have changed.
def self.load_rc_files
rc_files_to_load.each do |file|
load_file_at_toplevel(file)
critical_section do
load_file_at_toplevel(file)
end
end
end
@ -62,7 +98,6 @@ class Pry
# Including: loading .pryrc, loading plugins, loading requires, and
# loading history.
def self.initial_session_setup
return unless initial_session?
@initial_session = false
@ -85,6 +120,7 @@ class Pry
# Pry.start(Object.new, :input => MyInput.new)
def self.start(target=nil, options={})
return if ENV['DISABLE_PRY']
options = options.to_hash
if in_critical_section?
output.puts "ERROR: Pry started inside Pry."
@ -93,7 +129,7 @@ class Pry
end
options[:target] = Pry.binding_for(target || toplevel_binding)
options[:hooks] = Pry::Hooks.from_hash options.delete(:hooks) if options.key?(:hooks)
initial_session_setup
# Unless we were given a backtrace, save the current one
@ -130,8 +166,10 @@ class Pry
def self.view_clip(obj, max_length = 60)
if obj.kind_of?(Module) && obj.name.to_s != "" && obj.name.to_s.length <= max_length
obj.name.to_s
elsif TOPLEVEL_BINDING.eval('self') == obj
# special case for 'main' object :)
elsif Pry.main == obj
# special-case to support jruby.
# fixed as of https://github.com/jruby/jruby/commit/d365ebd309cf9df3dde28f5eb36ea97056e0c039
# we can drop in the future.
obj.to_s
elsif Pry.config.prompt_safe_objects.any? { |v| v === obj } && obj.inspect.length <= max_length
obj.inspect
@ -189,7 +227,6 @@ class Pry
def self.default_editor_for_platform
return ENV['VISUAL'] if ENV['VISUAL'] and not ENV['VISUAL'].empty?
return ENV['EDITOR'] if ENV['EDITOR'] and not ENV['EDITOR'].empty?
if Helpers::BaseHelpers.windows?
'notepad'
else
@ -200,15 +237,22 @@ class Pry
end
def self.auto_resize!
ver = Readline::VERSION
if ver[/edit/i]
Pry.config.input # by default, load Readline
if !defined?(Readline) || Pry.config.input != Readline
warn "Sorry, you must be using Readline for Pry.auto_resize! to work."
return
end
if Readline::VERSION =~ /edit/i
warn <<-EOT
Readline version #{ver} detected - will not auto_resize! correctly.
Readline version #{Readline::VERSION} detected - will not auto_resize! correctly.
For the fix, use GNU Readline instead:
https://github.com/guard/guard/wiki/Add-proper-Readline-support-to-Ruby-on-Mac-OS-X
EOT
return
end
trap :WINCH do
begin
Readline.set_screen_size(*Terminal.size!)
@ -223,105 +267,10 @@ Readline version #{ver} detected - will not auto_resize! correctly.
end
end
def self.set_config_defaults
config.input = Readline
config.output = $stdout
config.commands = Pry::Commands
config.prompt_name = DEFAULT_PROMPT_NAME
config.prompt = DEFAULT_PROMPT
config.prompt_safe_objects = DEFAULT_PROMPT_SAFE_OBJECTS
config.print = DEFAULT_PRINT
config.exception_handler = DEFAULT_EXCEPTION_HANDLER
config.exception_whitelist = DEFAULT_EXCEPTION_WHITELIST
config.default_window_size = 5
config.hooks = DEFAULT_HOOKS
config.color = Helpers::BaseHelpers.use_ansi_codes?
config.pager = true
config.system = DEFAULT_SYSTEM
config.editor = default_editor_for_platform
config.should_load_rc = true
config.should_load_local_rc = true
config.should_trap_interrupts = Helpers::BaseHelpers.jruby?
config.disable_auto_reload = false
config.command_prefix = ""
config.auto_indent = Helpers::BaseHelpers.use_ansi_codes?
config.correct_indent = true
config.collision_warning = false
config.output_prefix = "=> "
if defined?(Bond) && Readline::VERSION !~ /editline/i
config.completer = Pry::BondCompleter.start
else
config.completer = Pry::InputCompleter.start
end
config.gist ||= OpenStruct.new
config.gist.inspecter = proc(&:pretty_inspect)
config.should_load_plugins = true
config.requires ||= []
config.should_load_requires = true
config.history ||= OpenStruct.new
config.history.should_save = true
config.history.should_load = true
config.history.file = File.expand_path("~/.pry_history") rescue nil
if config.history.file.nil?
config.should_load_rc = false
config.history.should_save = false
config.history.should_load = false
end
config.control_d_handler = DEFAULT_CONTROL_D_HANDLER
config.memory_size = 100
config.extra_sticky_locals = {}
config.ls ||= OpenStruct.new({
:heading_color => :bright_blue,
:public_method_color => :default,
:private_method_color => :blue,
:protected_method_color => :blue,
:method_missing_color => :bright_red,
:local_var_color => :yellow,
:pry_var_color => :default, # e.g. _, _pry_, _file_
:instance_var_color => :blue, # e.g. @foo
:class_var_color => :bright_blue, # e.g. @@foo
:global_var_color => :default, # e.g. $CODERAY_DEBUG, $eventmachine_library
:builtin_global_color => :cyan, # e.g. $stdin, $-w, $PID
:pseudo_global_color => :cyan, # e.g. $~, $1..$9, $LAST_MATCH_INFO
:constant_color => :default, # e.g. VERSION, ARGF
:class_constant_color => :blue, # e.g. Object, Kernel
:exception_constant_color => :magenta, # e.g. Exception, RuntimeError
:unloaded_constant_color => :yellow, # Any constant that is still in .autoload? state
# What should separate items listed by ls?
:separator => " ",
# Any methods defined on these classes, or modules included into these classes, will not
# be shown by ls unless the -v flag is used.
# A user of Rails may wih to add ActiveRecord::Base to the list.
# add the following to your .pryrc:
# Pry.config.ls.ceiling << ActiveRecord::Base if defined? ActiveRecordBase
:ceiling => [Object, Module, Class]
})
end
# Set all the configurable options back to their default values
def self.reset_defaults
set_config_defaults
@initial_session = true
self.custom_completions = DEFAULT_CUSTOM_COMPLETIONS
self.config = Pry::Config.new Pry::Config::Default.new
self.cli = false
self.current_line = 1
self.line_buffer = [""]
@ -331,9 +280,6 @@ Readline version #{ver} detected - will not auto_resize! correctly.
# Basic initialization.
def self.init
@plugin_manager ||= PluginManager.new
self.config ||= Config.new
self.history ||= History.new
reset_defaults
locate_plugins
end
@ -347,7 +293,7 @@ Readline version #{ver} detected - will not auto_resize! correctly.
if Binding === target
target
else
if TOPLEVEL_BINDING.eval('self') == target
if Pry.main == target
TOPLEVEL_BINDING
else
target.__binding__

View file

@ -1,5 +1,4 @@
require "pry/indent"
# -*- coding: utf-8 -*-
##
# Pry is a powerful alternative to the standard IRB shell for Ruby. It
# features syntax highlighting, a flexible plugin architecture, runtime
@ -21,54 +20,27 @@ require "pry/indent"
# * https://github.com/pry/pry
# * the IRC channel, which is #pry on the Freenode network
#
class Pry
attr_accessor :input
attr_accessor :output
attr_accessor :commands
attr_accessor :print
attr_accessor :exception_handler
attr_accessor :quiet
alias :quiet? :quiet
attr_accessor :custom_completions
attr_accessor :binding_stack
attr_accessor :custom_completions
attr_accessor :eval_string
attr_accessor :backtrace
attr_accessor :suppress_output
attr_accessor :last_result
attr_accessor :last_file
attr_accessor :last_dir
attr_reader :last_exception
attr_reader :command_state
attr_reader :exit_value
attr_reader :input_array
attr_reader :output_array
attr_reader :config
attr_accessor :backtrace
attr_accessor :extra_sticky_locals
attr_accessor :suppress_output
# This is exposed via Pry::Command#state.
attr_reader :command_state
attr_reader :exit_value
attr_reader :hooks # Special treatment as we want to alert people of the
# changed API.
# FIXME: This is a hack to alert people of the new API.
# @param [Pry::Hooks] hooks
def hooks=(hooks)
if hooks.is_a?(Hash)
warn "Hash-based hooks are now deprecated! Use a `Pry::Hooks` object " \
"instead! http://rubydoc.info/github/pry/pry/master/Pry/Hooks"
@hooks = Pry::Hooks.from_hash(hooks)
else
@hooks = hooks
end
end
extend Pry::Config::Convenience
config_shortcut *Pry::Config.shortcuts
EMPTY_COMPLETIONS = [].freeze
# Create a new {Pry} instance.
# @param [Hash] options
@ -95,62 +67,19 @@ class Pry
@indent = Pry::Indent.new
@command_state = {}
@eval_string = ""
@backtrace = options[:backtrace] || caller
refresh_config(options)
@backtrace = options.delete(:backtrace) || caller
@config = Pry::Config.new
config.merge!(options)
push_prompt(config.prompt)
@input_array = Pry::HistoryArray.new config.memory_size
@output_array = Pry::HistoryArray.new config.memory_size
@custom_completions = config.command_completions
push_initial_binding(options[:target])
set_last_result nil
@input_array << nil # add empty input so _in_ and _out_ match
# yield the binding_stack to the hook for modification
@input_array << nil
exec_hook(:when_started, options[:target], options, self)
end
# Refresh the Pry instance settings from the Pry class.
# Allows options to be specified to override settings from Pry class.
# @param [Hash] options The options to override Pry class settings
# for this instance.
def refresh_config(options={})
defaults = {}
attributes = [
:input, :output, :commands, :print, :quiet,
:exception_handler, :hooks, :custom_completions,
:prompt, :memory_size, :extra_sticky_locals
]
attributes.each do |attribute|
defaults[attribute] = Pry.send attribute
end
defaults.merge!(options).each do |key, value|
send("#{key}=", value) if respond_to?("#{key}=")
end
true
end
# Initialize this instance by pushing its initial context into the binding
# stack. If no target is given, start at the top level.
def push_initial_binding(target=nil)
push_binding(target || Pry.toplevel_binding)
end
# The currently active `Binding`.
# @return [Binding] The currently active `Binding` for the session.
def current_binding
binding_stack.last
end
alias current_context current_binding # support previous API
# Push a binding for the given object onto the stack. If this instance is
# currently stopped, mark it as usable again.
def push_binding(object)
@stopped = false
binding_stack << Pry.binding_for(object)
end
# The current prompt.
# This is the prompt at the top of the prompt stack.
#
@ -171,14 +100,43 @@ class Pry
end
end
# Initialize this instance by pushing its initial context into the binding
# stack. If no target is given, start at the top level.
def push_initial_binding(target=nil)
push_binding(target || Pry.toplevel_binding)
end
# The currently active `Binding`.
# @return [Binding] The currently active `Binding` for the session.
def current_binding
binding_stack.last
end
alias current_context current_binding # support previous API
# Push a binding for the given object onto the stack. If this instance is
# currently stopped, mark it as usable again.
def push_binding(object)
@stopped = false
binding_stack << Pry.binding_for(object)
end
def prompt=(new_prompt)
if prompt_stack.empty?
push_prompt new_prompt
else
prompt_stack[-1] = new_prompt
end
end
# Generate completions.
# @param [String] input What the user has typed so far
# @return [Array<String>] Possible completions
def complete(input)
return EMPTY_COMPLETIONS unless config.completer
Pry.critical_section do
Pry.config.completer.call(input, :target => current_binding,
:pry => self,
:custom_completions => instance_eval(&custom_completions))
config.completer.call input, :target => current_binding,
:pry => self,
:custom_completions => custom_completions
end
end
@ -218,21 +176,19 @@ class Pry
# @yield The block that defines the content of the local. The local
# will be refreshed at each tick of the repl loop.
def add_sticky_local(name, &block)
sticky_locals[name] = block
config.extra_sticky_locals[name] = block
end
# @return [Hash] The currently defined sticky locals.
def sticky_locals
@sticky_locals ||= {
:_in_ => proc { @input_array },
:_out_ => proc { @output_array },
:_pry_ => self,
:_ex_ => proc { last_exception },
:_file_ => proc { last_file },
:_dir_ => proc { last_dir },
:_ => proc { last_result },
:__ => proc { @output_array[-2] }
}.merge(extra_sticky_locals)
{ _in_: input_array,
_out_: output_array,
_pry_: self,
_ex_: last_exception,
_file_: last_file,
_dir_: last_dir,
_: proc { last_result },
__: proc { output_array[-2] }
}.merge(config.extra_sticky_locals)
end
# Reset the current eval string. If the user has entered part of a multiline
@ -286,7 +242,7 @@ class Pry
def handle_line(line, options)
if line.nil?
Pry.config.control_d_handler.call(@eval_string, self)
config.control_d_handler.call(@eval_string, self)
return
end
@ -391,7 +347,7 @@ class Pry
if last_result_is_exception?
exception_handler.call(output, result, self)
elsif should_print?
print.call(output, result)
print.call(output, result, self)
else
# nothin'
end
@ -568,7 +524,7 @@ class Pry
open_token = @indent.open_delimiters.any? ? @indent.open_delimiters.last :
@indent.stack.last
c = OpenStruct.new(
c = Pry::Config.from_hash({
:object => object,
:nesting_level => binding_stack.size - 1,
:open_token => open_token,
@ -579,7 +535,7 @@ class Pry
:binding_stack => binding_stack,
:input_array => input_array,
:eval_string => @eval_string,
:cont => !@eval_string.empty?)
:cont => !@eval_string.empty?})
Pry.critical_section do
# If input buffer is empty then use normal prompt

View file

@ -179,10 +179,7 @@ class Pry
end
end
if input == Readline
if !$stdout.tty? && $stdin.tty? && !Pry::Helpers::BaseHelpers.windows?
Readline.output = File.open('/dev/tty', 'w')
end
if defined?(Readline) and input == Readline
input_readline(current_prompt, false) # false since we'll add it manually
elsif defined? Coolline and input.is_a? Coolline
input_readline(current_prompt)

View file

@ -44,6 +44,11 @@ class Pry
content.lines.each do |line|
break unless _pry_.eval line, :generated => true
end
unless _pry_.eval_string.empty?
_pry_.output.puts "#{_pry_.eval_string}...exception encountered, going interactive!"
interactive_mode(_pry_)
end
end
# Define a few extra commands useful for flipping back & forth

View file

@ -44,7 +44,8 @@ class Pry::Terminal
require 'io/console'
$stdout.winsize if $stdout.tty? and $stdout.respond_to?(:winsize)
rescue LoadError
# They're probably on 1.8 without the io-console gem. We'll keep trying.
# They probably don't have the io/console stdlib or the io-console gem.
# We'll keep trying.
end
def screen_size_according_to_env
@ -53,7 +54,7 @@ class Pry::Terminal
end
def screen_size_according_to_readline
if Readline.respond_to?(:get_screen_size)
if defined?(Readline) && Readline.respond_to?(:get_screen_size)
size = Readline.get_screen_size
size if nonzero_column?(size)
end

View file

@ -47,10 +47,6 @@ module PryTestHelpers
end
end
def mri18_and_no_real_source_location?
Pry::Helpers::BaseHelpers.mri_18? && !(Method.instance_method(:source_location).owner == Method)
end
# Open a temp file and yield it to the block, closing it after
# @return [String] The path of the temp file
def temp_file(ext='.rb')

View file

@ -66,28 +66,12 @@ class Pry
end
# Returns an array of the names of the constants accessible in the wrapped
# module. This provides a consistent interface between 1.8 and 1.9 and also
# avoids the problem of accidentally calling the singleton method
# `Module.constants`.
# module. This avoids the problem of accidentally calling the singleton
# method `Module.constants`.
# @param [Boolean] inherit Include the names of constants from included
# modules?
def constants(inherit = true)
method = Module.instance_method(:constants).bind(@wrapped)
# If we're on 1.8, we have to manually remove ancestors' constants. If
# we're on 1.9, though, it's better to use the built-in `inherit` param,
# since it doesn't do things like incorrectly remove Pry::Config.
if method.arity == 0
consts = method.call
if !inherit
ancestors_ = Pry::Method.safe_send(@wrapped, :ancestors)
consts -= (ancestors_ - [@wrapped]).map(&:constants).flatten
end
else
consts = method.call(inherit)
end
consts
Module.instance_method(:constants).bind(@wrapped).call(inherit)
end
# The prefix that would appear before methods defined on this class.
@ -259,7 +243,7 @@ class Pry
# @return [Enumerator, Array] on JRuby 1.9 and higher returns Array, on
# other rubies returns Enumerator
def candidates
enum = generator.new do |y|
enum = Enumerator.new do |y|
(0...number_of_candidates).each do |num|
y.yield candidate(num)
end
@ -292,18 +276,6 @@ class Pry
private
# Ruby 1.8 doesn't support `Enumerator` (it's called Generator instead)
#
# @return [Object] Return the appropriate generator class.
def generator
@generator ||= if defined?(Enumerator)
Enumerator
else
require 'generator'
Generator
end
end
# @return [Pry::WrappedModule::Candidate] The candidate with the
# highest rank, that is the 'monkey patch' of this module with the
# highest number of methods, which contains a source code line that
@ -367,22 +339,7 @@ class Pry
# given module.
# @return [Array<Pry::Method>]
def all_methods_for(mod)
all_from_common(mod, :instance_method) + all_from_common(mod, :method)
end
# FIXME: a variant of this method is also found in Pry::Method
def all_from_common(mod, method_type)
%w(public protected private).map do |visibility|
safe_send(mod, :"#{visibility}_#{method_type}s", false).select do |method_name|
if method_type == :method
safe_send(mod, method_type, method_name).owner == class << mod; self; end
else
safe_send(mod, method_type, method_name).owner == mod
end
end.map do |method_name|
Pry::Method.new(safe_send(mod, method_type, method_name), :visibility => visibility.to_sym)
end
end.flatten
Pry::Method.all_from_obj(mod, false) + Pry::Method.all_from_class(mod, false)
end
def nested_module?(parent, name)

View file

@ -27,5 +27,5 @@ Gem::Specification.new do |s|
s.add_development_dependency 'mocha', '~> 0.13.1'
s.add_development_dependency 'simplecov'
# TODO: make this a plain dependency:
s.add_development_dependency 'bond', '~> 0.4.2'
s.add_development_dependency 'bond', '~> 0.5.0'
end

View file

@ -60,7 +60,7 @@ describe Pry::Hooks do
Pry::CLI.add_options do
on :optiontest, "A test option"
end.process_options do |opts|
end.add_option_processor do |opts|
run = true if opts.present?(:optiontest)
end.parse_options(["--optiontest"])
@ -74,9 +74,9 @@ describe Pry::Hooks do
Pry::CLI.add_options do
on :optiontest, "A test option"
on :optiontest2, "Another test option"
end.process_options do |opts|
end.add_option_processor do |opts|
run = true if opts.present?(:optiontest)
end.process_options do |opts|
end.add_option_processor do |opts|
run2 = true if opts.present?(:optiontest2)
end.parse_options(["--optiontest", "--optiontest2"])

View file

@ -473,22 +473,23 @@ describe "commands" do
end
end
klass.commands.include?("nesting").should == true
klass.commands.include?("jump-to").should == true
klass.commands.include?("cd").should == true
klass.commands.include?("v").should == true
klass.to_hash.include?("nesting").should == true
klass.to_hash.include?("jump-to").should == true
klass.to_hash.include?("cd").should == true
klass.to_hash.include?("v").should == true
end
it 'should change description of a command using desc' do
klass = Pry::CommandSet.new do
import Pry::Commands
end
orig = klass.commands["help"].description
orig = klass["help"].description
klass.instance_eval do
desc "help", "blah"
end
klass.commands["help"].description.should.not == orig
klass.commands["help"].description.should == "blah"
commands = klass.to_hash
commands["help"].description.should.not == orig
commands["help"].description.should == "blah"
end
it 'should enable an inherited method to access opts and output and target, due to instance_exec' do
@ -512,8 +513,8 @@ describe "commands" do
import_from Pry::Commands, "ls", "jump-to"
end
klass.commands.include?("ls").should == true
klass.commands.include?("jump-to").should == true
klass.to_hash.include?("ls").should == true
klass.to_hash.include?("jump-to").should == true
end
it 'should delete some inherited commands when using delete method' do
@ -525,13 +526,14 @@ describe "commands" do
delete "ls"
end
klass.commands.include?("nesting").should == true
klass.commands.include?("jump-to").should == true
klass.commands.include?("cd").should == true
klass.commands.include?("v").should == true
klass.commands.include?("show-doc").should == false
klass.commands.include?("show-method").should == false
klass.commands.include?("ls").should == false
commands = klass.to_hash
commands.include?("nesting").should == true
commands.include?("jump-to").should == true
commands.include?("cd").should == true
commands.include?("v").should == true
commands.include?("show-doc").should == false
commands.include?("show-method").should == false
commands.include?("ls").should == false
end
it 'should override some inherited commands' do

View file

@ -167,7 +167,7 @@ describe Pry::CommandSet do
it 'should set the descriptions of commands' do
@set.command('foo', 'some stuff') {}
@set.commands['foo'].description.should == 'some stuff'
@set['foo'].description.should == 'some stuff'
end
describe "aliases" do
@ -176,8 +176,8 @@ describe Pry::CommandSet do
@set.command('foo', 'stuff') { run = true }
@set.alias_command 'bar', 'foo'
@set.commands['bar'].match.should == 'bar'
@set.commands['bar'].description.should == 'Alias for `foo`'
@set['bar'].match.should == 'bar'
@set['bar'].description.should == 'Alias for `foo`'
@set.run_command @ctx, 'bar'
run.should == true
@ -203,12 +203,12 @@ describe Pry::CommandSet do
@set.command('foo', 'stuff', :shellwords => true, :interpolate => false) { run = true }
@set.alias_command 'bar', 'foo'
@set.commands['bar'].options[:shellwords].should == @set.commands['foo'].options[:shellwords]
@set.commands['bar'].options[:interpolate].should == @set.commands['foo'].options[:interpolate]
@set['bar'].options[:shellwords].should == @set['foo'].options[:shellwords]
@set['bar'].options[:interpolate].should == @set['foo'].options[:interpolate]
# however some options should not be inherited
@set.commands['bar'].options[:listing].should.not == @set.commands['foo'].options[:listing]
@set.commands['bar'].options[:listing].should == "bar"
@set['bar'].options[:listing].should.not == @set['foo'].options[:listing]
@set['bar'].options[:listing].should == "bar"
end
it 'should be able to specify alias\'s description when aliasing' do
@ -216,8 +216,8 @@ describe Pry::CommandSet do
@set.command('foo', 'stuff') { run = true }
@set.alias_command 'bar', 'foo', :desc => "tobina"
@set.commands['bar'].match.should == 'bar'
@set.commands['bar'].description.should == "tobina"
@set['bar'].match.should == 'bar'
@set['bar'].description.should == "tobina"
@set.run_command @ctx, 'bar'
run.should == true
@ -228,8 +228,8 @@ describe Pry::CommandSet do
@set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true }
@set.alias_command 'bar', 'foo1'
@set.commands['bar'].match.should == 'bar'
@set.commands['bar'].description.should == 'Alias for `foo1`'
@set['bar'].match.should == 'bar'
@set['bar'].description.should == 'Alias for `foo1`'
@set.run_command @ctx, 'bar'
run.should == true
@ -240,7 +240,7 @@ describe Pry::CommandSet do
@set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true }
@set.alias_command /^b.r/, 'foo1', :listing => "bar"
@set.commands[/^b.r/].options[:listing].should == "bar"
@set.to_hash[/^b.r/].options[:listing].should == "bar"
end
it "should set description to default if description parameter is nil" do
@ -248,7 +248,7 @@ describe Pry::CommandSet do
@set.command(/^foo1/, 'stuff', :listing => 'foo') { run = true }
@set.alias_command "bar", 'foo1'
@set.commands["bar"].description.should == "Alias for `foo1`"
@set["bar"].description.should == "Alias for `foo1`"
end
end
@ -256,7 +256,7 @@ describe Pry::CommandSet do
@set.command('foo', 'bar') {}
@set.desc 'foo', 'baz'
@set.commands['foo'].description.should == 'baz'
@set['foo'].description.should == 'baz'
end
it 'should get the descriptions of commands' do
@ -342,12 +342,12 @@ describe Pry::CommandSet do
it 'should provide a :listing for a command that defaults to its name' do
@set.command 'foo', "" do;end
@set.commands['foo'].options[:listing].should == 'foo'
@set['foo'].options[:listing].should == 'foo'
end
it 'should provide a :listing for a command that differs from its name' do
@set.command 'foo', "", :listing => 'bar' do;end
@set.commands['foo'].options[:listing].should == 'bar'
@set['foo'].options[:listing].should == 'bar'
end
it "should provide a 'help' command" do
@ -392,9 +392,9 @@ describe Pry::CommandSet do
listing = "bing"
@set.command('foo') { }
@set.rename_command('bar', 'foo', :description => desc, :listing => listing, :keep_retval => true)
@set.commands['bar'].description.should == desc
@set.commands['bar'].options[:listing].should == listing
@set.commands['bar'].options[:keep_retval].should == true
@set['bar'].description.should == desc
@set['bar'].options[:listing].should == listing
@set['bar'].options[:keep_retval].should == true
end
end

View file

@ -94,7 +94,7 @@ describe "Pry::Command" do
#
end
mock_command(@set.commands['help'], %w(oolon-colluphid), :command_set => @set).output.should =~ /Raving Atheist/
mock_command(@set['help'], %w(oolon-colluphid), :command_set => @set).output.should =~ /Raving Atheist/
end
it 'should use slop to generate the help for classy commands' do
@ -104,7 +104,7 @@ describe "Pry::Command" do
end
end
mock_command(@set.commands['help'], %w(eddie), :command_set => @set).output.should =~ /Over-cheerful/
mock_command(@set['help'], %w(eddie), :command_set => @set).output.should =~ /Over-cheerful/
end
it 'should provide --help for classy commands' do
@ -664,10 +664,8 @@ describe "Pry::Command" do
pry_eval('my---test').should =~ /my-testmy-test/
end
if !mri18_and_no_real_source_location?
it "shows the source of the process method" do
pry_eval('show-source my-test').should =~ /output.puts command_name/
end
it "shows the source of the process method" do
pry_eval('show-source my-test').should =~ /output.puts command_name/
end
describe "command options hash" do
@ -805,17 +803,17 @@ describe "Pry::Command" do
end
it 'should be correct for default commands' do
@set.commands["help"].group.should == "Help"
@set["help"].group.should == "Help"
end
it 'should not change once it is initialized' do
@set.commands["magic"].group("-==CD COMMAND==-")
@set.commands["magic"].group.should == "Not for a public use"
@set["magic"].group("-==CD COMMAND==-")
@set["magic"].group.should == "Not for a public use"
end
it 'should not disappear after the call without parameters' do
@set.commands["magic"].group
@set.commands["magic"].group.should == "Not for a public use"
@set["magic"].group
@set["magic"].group.should == "Not for a public use"
end
end
end

View file

@ -35,6 +35,16 @@ describe "edit" do
FileUtils.rm(@tf_path) if File.exists?(@tf_path)
end
it "should not allow patching any known kind of file" do
["file.rb", "file.c", "file.py", "file.yml", "file.gemspec",
"/tmp/file", "\\\\Temp\\\\file"].each do |file|
proc {
pry_eval "edit -p #{file}"
}.should.raise(NotImplementedError).
message.should =~ /Cannot yet patch false objects!/
end
end
it "should invoke Pry.config.editor with absolutified filenames" do
pry_eval 'edit lib/pry.rb'
@file.should == File.expand_path('lib/pry.rb')

View file

@ -1,70 +1,63 @@
require 'helper'
# we turn off the test for MRI 1.8 because our source_location hack
# for C methods actually runs the methods - and since it runs ALL
# methods (in an attempt to find a match) it runs 'exit' and aborts
# the test, causing a failure. We should fix this in the future by
# blacklisting certain methods for 1.8 MRI (such as exit, fork, and so on)
unless Pry::Helpers::BaseHelpers.mri_18?
MyKlass = Class.new do
def hello
"timothy"
MyKlass = Class.new do
def hello
"timothy"
end
def goodbye
"jenny"
end
def tea_tim?
"timothy"
end
def tea_time?
"polly"
end
end
describe "find-method" do
describe "find matching methods by name regex (-n option)" do
it "should find a method by regex" do
pry_eval("find-method hell MyKlass").should =~
/MyKlass.*?hello/m
end
def goodbye
"jenny"
end
def tea_tim?
"timothy"
end
def tea_time?
"polly"
it "should NOT match a method that does not match the regex" do
pry_eval("find-method hell MyKlass").should.not =~
/MyKlass.*?goodbye/m
end
end
describe "find-method" do
describe "find matching methods by name regex (-n option)" do
it "should find a method by regex" do
pry_eval("find-method hell MyKlass").should =~
/MyKlass.*?hello/m
end
it "should NOT match a method that does not match the regex" do
pry_eval("find-method hell MyKlass").should.not =~
/MyKlass.*?goodbye/m
end
end
describe "find matching methods by content regex (-c option)" do
it "should find a method by regex" do
pry_eval("find-method -c timothy MyKlass").should =~
/MyKlass.*?hello/m
end
it "should NOT match a method that does not match the regex" do
pry_eval("find-method timothy MyKlass").should.not =~
/MyKlass.*?goodbye/m
end
end
it "should work with badly behaved constants" do
MyKlass::X = Object.new
def (MyKlass::X).hash
raise "mooo"
end
describe "find matching methods by content regex (-c option)" do
it "should find a method by regex" do
pry_eval("find-method -c timothy MyKlass").should =~
/MyKlass.*?hello/m
end
it "should escape regexes correctly" do
good = /tea_time\?/
bad = /tea_tim\?/
pry_eval('find-method tea_time? MyKlass').should =~ good
pry_eval('find-method tea_time? MyKlass').should =~ good
pry_eval('find-method tea_time\? MyKlass').should.not =~ bad
pry_eval('find-method tea_time\? MyKlass').should =~ good
it "should NOT match a method that does not match the regex" do
pry_eval("find-method timothy MyKlass").should.not =~
/MyKlass.*?goodbye/m
end
end
Object.remove_const(:MyKlass)
it "should work with badly behaved constants" do
MyKlass::X = Object.new
def (MyKlass::X).hash
raise "mooo"
end
pry_eval("find-method -c timothy MyKlass").should =~
/MyKlass.*?hello/m
end
it "should escape regexes correctly" do
good = /tea_time\?/
bad = /tea_tim\?/
pry_eval('find-method tea_time? MyKlass').should =~ good
pry_eval('find-method tea_time? MyKlass').should =~ good
pry_eval('find-method tea_time\? MyKlass').should.not =~ bad
pry_eval('find-method tea_time\? MyKlass').should =~ good
end
end
Object.remove_const(:MyKlass)

View file

@ -1,7 +1,6 @@
require 'helper'
describe "gem-list" do
# fixing bug for 1.8 compat
it 'should not raise when invoked' do
proc {
pry_eval(self, 'gem-list')

View file

@ -34,18 +34,22 @@ describe "ls" do
end
end
if defined?(BasicObject)
describe "BasicObject" do
it "should work on BasicObject" do
pry_eval("ls BasicObject.new").should =~ /BasicObject#methods:.*__send__/m
end
describe "BasicObject" do
it "should work on BasicObject" do
pry_eval("ls BasicObject.new").should =~ /BasicObject#methods:.*__send__/m
end
it "should work on subclasses of BasicObject" do
pry_eval(
"class LessBasic < BasicObject; def jaroussky; 5; end; end",
"ls LessBasic.new"
).should =~ /LessBasic#methods:.*jaroussky/m
end
it "should work on subclasses of BasicObject" do
pry_eval(
"class LessBasic < BasicObject; def jaroussky; 5; end; end",
"ls LessBasic.new"
).should =~ /LessBasic#methods:.*jaroussky/m
end
end
describe "immediates" do
it "should work on Fixnum" do
pry_eval("ls 5").should =~ /Fixnum#methods:.*modulo/m
end
end
@ -92,6 +96,11 @@ describe "ls" do
test.should.not.raise
end
it "should show error message when instance is given with -M option" do
error = lambda{ pry_eval("ls -M String.new") }.should.raise(Pry::CommandError)
error.message.should.match(/-M only makes sense with a Module or a Class/)
end
# see: https://travis-ci.org/pry/pry/jobs/5071918
unless Pry::Helpers::BaseHelpers.rbx?

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,119 @@
require 'helper'
describe "watch expression" do
# Custom eval that will:
# 1) Create an instance of pry that can use for multiple calls
# 2) Exercise the after_eval hook
# 3) Return the output
def eval(expr)
output = @tester.eval expr
@tester.pry.hooks.exec_hook :after_eval, nil, @tester.pry
output
end
before do
@tester = pry_tester
@tester.pry.hooks.clear :after_eval
eval "watch --delete"
end
it "registers the after_eval hook" do
eval 'watch 1+1'
@tester.pry.hooks.hook_exists?(:after_eval, :watch_expression).should == true
end
it "prints no watched expressions" do
eval('watch').should =~ /No watched expressions/
end
it "watches an expression" do
eval "watch 1+1"
eval('watch').should =~ /=> 2/
end
it "watches a local variable" do
eval 'foo = :bar'
eval 'watch foo'
eval('watch').should =~ /=> :bar/
end
it "prints when an expression changes" do
ReplTester.start do
input 'a = 1'
output '=> 1'
input 'watch a'
output "Watching a\nwatch: a => 1"
input "a = 2"
output "watch: a => 2\n=> 2"
end
end
it "prints when an expression is mutated" do
ReplTester.start do
input 'a = "one"'
output '=> "one"'
input 'watch a'
output %(Watching a\nwatch: a => "one")
input "a.sub! 'o', 'p'"
output %(watch: a => "pne"\n=> "pne")
end
end
it "doesn't print when an expresison remains the same" do
ReplTester.start do
input 'a = 1'
output '=> 1'
input 'watch a'
output "Watching a\nwatch: a => 1"
input "a = 1"
output "=> 1"
end
end
it "continues to work if you start a second pry instance" do
ReplTester.start do
input 'a = 1'
output '=> 1'
input 'watch a'
output "Watching a\nwatch: a => 1"
input "a = 2"
output "watch: a => 2\n=> 2"
end
ReplTester.start do
input 'b = 1'
output '=> 1'
input 'watch b'
output "Watching b\nwatch: b => 1"
input "b = 2"
output "watch: b => 2\n=> 2"
end
end
describe "deleting expressions" do
before do
eval 'watch :keeper'
eval 'watch :delete'
eval 'watch -d 2'
end
it "keeps keeper" do
eval('watch').should =~ /keeper/
end
it "deletes delete" do
eval('watch').should.not =~ /delete/
end
end
end

View file

@ -41,16 +41,14 @@ describe "whereami" do
Object.remove_const(:Cor)
end
if defined?(BasicObject)
it 'should work in BasicObjects' do
cor = Class.new(BasicObject) do
def blimey!
::Kernel.binding # omnom
end
end.new.blimey!
it 'should work in BasicObjects' do
cor = Class.new(BasicObject) do
def blimey!
::Kernel.binding # omnom
end
end.new.blimey!
pry_eval(cor, 'whereami').should =~ /::Kernel.binding [#] omnom/
end
pry_eval(cor, 'whereami').should =~ /::Kernel.binding [#] omnom/
end
it 'should show description and correct code when __LINE__ and __FILE__ are outside @method.source_location' do

View file

@ -6,16 +6,22 @@ def completer_test(bind, pry=nil, assert_flag=true)
return proc {|*symbols| symbols.each(&test) }
end
if defined?(Bond) && Readline::VERSION !~ /editline/i
describe 'bond-based completion' do
it 'should pull in Bond by default' do
Pry.config.completer.should == Pry::BondCompleter
describe 'Bond-based completion' do
before do
@local = Pry::Config.new Pry::Config::Default.new
@local.completer
end
it "should use Bond if it's available" do
if defined?(Bond) && defined?(Readline) && Readline::VERSION !~ /editline/i
@local.completer.should == Pry::BondCompleter
else
@local.completer.should == Pry::InputCompleter
end
end
end
describe Pry::InputCompleter do
before do
# The AMQP gem has some classes like this:
# pry(main)> AMQP::Protocol::Test::ContentOk.name

122
spec/config_spec.rb Normal file
View file

@ -0,0 +1,122 @@
require 'helper'
describe Pry::Config do
describe "reserved keys" do
it "raises an ArgumentError on assignment of a reserved key" do
local = Pry::Config.from_hash({})
Pry::Config::RESERVED_KEYS.each do |key|
should.raise(ArgumentError) { local[key] = 1 }
end
end
end
describe "traversal to parent" do
it "traverses back to the parent when a local key is not found" do
local = Pry::Config.new Pry::Config.from_hash(foo: 1)
local.foo.should == 1
end
it "stores a local key and prevents traversal to the parent" do
local = Pry::Config.new Pry::Config.from_hash(foo: 1)
local.foo = 2
local.foo.should == 2
end
it "duplicates a copy on read from the parent" do
ukraine = "i love"
local = Pry::Config.new Pry::Config.from_hash(home: ukraine)
local.home.equal?(ukraine).should == false
end
it "traverses through a chain of parents" do
root = Pry::Config.from_hash({foo: 21})
local1 = Pry::Config.new(root)
local2 = Pry::Config.new(local1)
local3 = Pry::Config.new(local2)
local3.foo.should == 21
end
end
describe ".from_hash" do
it "returns an object without a default when given 1 argument" do
local = Pry::Config.from_hash({})
local.instance_variable_get(:@default).should == nil
end
it "returns an object with a default when given 2 arguments" do
default = Pry::Config.new(nil)
local = Pry::Config.from_hash({}, default)
local.instance_variable_get(:@default).should == default
end
end
describe "#keys" do
it "returns an array of local keys" do
root = Pry::Config.from_hash({zoo: "boo"}, nil)
local = Pry::Config.from_hash({foo: "bar"}, root)
local.keys.should == ["foo"]
end
end
describe "#==" do
it "compares equality through the underlying lookup table" do
local1 = Pry::Config.new(nil)
local2 = Pry::Config.new(nil)
local1.foo = "hi"
local2.foo = "hi"
local1.should == local2
end
it "compares equality against an object who does not implement #to_hash" do
local1 = Pry::Config.new(nil)
local1.should.not == Object.new
end
end
describe "#forget" do
it "forgets a local key" do
local = Pry::Config.new Pry::Config.from_hash(foo: 1)
local.foo = 2
local.foo.should == 2
local.forget(:foo)
local.foo.should == 1
end
end
describe "#to_hash" do
it "provides a copy of local key & value pairs as a Hash" do
local = Pry::Config.new Pry::Config.from_hash(bar: true)
local.foo = "21"
local.to_hash.should == { "foo" => "21" }
end
it "returns a duplicate of the lookup table" do
local = Pry::Config.new(nil)
local.to_hash.merge!("foo" => 42)
local.foo.should.not == 42
end
end
describe "#merge!" do
it "can merge a Hash-like object" do
local = Pry::Config.new(nil)
local.merge! Pry::Config.from_hash(foo: 21)
local.foo.should == 21
end
it "can merge a Hash" do
local = Pry::Config.new(nil)
local.merge!(foo: 21)
local.foo.should == 21
end
end
describe "#[]=" do
it "stores keys as strings" do
local = Pry::Config.from_hash({})
local[:zoo] = "hello"
local.to_hash.should == { "zoo" => "hello" }
end
end
end

View file

@ -9,11 +9,11 @@ unless Object.const_defined? 'Pry'
end
require 'mocha/api'
require "ostruct"
require 'pry/test/helper'
require 'helpers/bacon'
require 'helpers/mock_pry'
require 'helpers/repl_tester'
require 'spec_helpers/bacon'
require 'spec_helpers/mock_pry'
require 'spec_helpers/repl_tester'
class Module
public :remove_const

View file

@ -0,0 +1,17 @@
require "bundler/setup"
require "bacon"
describe "Readline" do
describe "on require of 'pry'" do
it "is not made available" do
require('pry').should.be.true
defined?(Readline).should.be.nil
end
end
describe "on invoke of 'pry'" do
it "is made available" do
Pry.start self, input: StringIO.new("exit-all\n"), output: StringIO.new
defined?(Readline).should == "constant"
end
end
end

View file

@ -144,7 +144,8 @@ describe Pry::Method do
m.name.should == "gag"
end
if defined?(BasicObject) && !Pry::Helpers::BaseHelpers.rbx? # rubinius issue 1921
# Temporarily disabled to work around rubinius/rubinius#2871.
unless Pry::Helpers::BaseHelpers.rbx?
it "should find the right method from a BasicObject" do
a = Class.new(BasicObject) { def gag; ::Kernel.binding; end; def self.line; __LINE__; end }
@ -433,8 +434,8 @@ describe Pry::Method do
it "should include the Pry::Method.instance_resolution_order of Class after the singleton classes" do
Pry::Method.resolution_order(LS::Top).should ==
[singleton_class(LS::Top), singleton_class(Object), (defined? BasicObject) && singleton_class(BasicObject)].compact +
Pry::Method.instance_resolution_order(Class)
[singleton_class(LS::Top), singleton_class(Object), singleton_class(BasicObject),
*Pry::Method.instance_resolution_order(Class)]
end
end
end
@ -496,15 +497,11 @@ describe Pry::Method do
end
end
unless Pry::Helpers::BaseHelpers.mri_18?
# Ruby 1.8 doesn't support this feature.
it 'should be able to find aliases for methods implemented in C' do
meth = Pry::Method(Hash.new.method(:key?))
aliases = Set.new(meth.aliases)
it 'should be able to find aliases for methods implemented in C' do
meth = Pry::Method(Hash.new.method(:key?))
aliases = Set.new(meth.aliases)
aliases.should == Set.new(["include?", "member?", "has_key?"])
end
aliases.should == Set.new(["include?", "member?", "has_key?"])
end
end
end

View file

@ -7,7 +7,7 @@ describe "Prompts" do
redirect_pry_io(InputTester.new("exit-all")) do
Pry.start(self, :prompt => proc { |v| config = v })
end
config.is_a?(OpenStruct).should == true
config.is_a?(Pry::Config).should == true
end
it 'should get full config object, when using a proc array' do
@ -15,7 +15,7 @@ describe "Prompts" do
redirect_pry_io(InputTester.new("exit-all")) do
Pry.start(self, :prompt => [proc { |v| config1 = v }, proc { |v| config2 = v }])
end
config1.is_a?(OpenStruct).should == true
config1.is_a?(Pry::Config).should == true
end
it 'should receive correct data in the config object' do

View file

@ -35,8 +35,9 @@ describe Pry do
end
it "should include the =>" do
pry = Pry.new
accumulator = StringIO.new
Pry.config.print.call(accumulator, [1])
pry.config.print.call(accumulator, [1], pry)
accumulator.string.should == "=> \[1\]\n"
end
@ -49,6 +50,16 @@ describe Pry do
end
end
describe "output_prefix" do
it "should be able to change output_prefix" do
pry = Pry.new
accumulator = StringIO.new
pry.config.output_prefix = "-> "
pry.config.print.call(accumulator, [1], pry)
accumulator.string.should == "-> \[1\]\n"
end
end
describe "color" do
before do
Pry.color = true
@ -59,19 +70,21 @@ describe Pry do
end
it "should colorize strings as though they were ruby" do
pry = Pry.new
accumulator = StringIO.new
colorized = CodeRay.scan("[1]", :ruby).term
Pry.config.print.call(accumulator, [1])
pry.config.print.call(accumulator, [1], pry)
accumulator.string.should == "=> #{colorized}\n"
end
it "should not colorize strings that already include color" do
pry = Pry.new
f = Object.new
def f.inspect
"\e[1;31mFoo\e[0m"
end
accumulator = StringIO.new
Pry.config.print.call(accumulator, f)
pry.config.print.call(accumulator, f, pry)
# We add an extra \e[0m to prevent color leak
accumulator.string.should == "=> \e[1;31mFoo\e[0m\e[0m\n"
end

View file

@ -47,7 +47,7 @@ describe "The whole thing" do
it "shouldn't break if we start a nested instance" do
ReplTester.start do
input 'Pry.start(10)'
input 'Pry.start(10, _pry_.config)'
output ''
prompt /10.*> $/

View file

@ -5,15 +5,11 @@ describe Pry do
@str_output = StringIO.new
end
if RUBY_VERSION =~ /1.9/
describe "Exotic object support" do
# regression test for exotic object support
it "Should not error when return value is a BasicObject instance" do
ReplTester.start do
input('BasicObject.new').should =~ /^=> #<BasicObject:/
end
describe "Exotic object support" do
# regression test for exotic object support
it "Should not error when return value is a BasicObject instance" do
ReplTester.start do
input('BasicObject.new').should =~ /^=> #<BasicObject:/
end
end
end
@ -89,11 +85,9 @@ describe Pry do
}.should.raise(NameError)
end
if defined?(BasicObject)
it 'should be able to operate inside the BasicObject class' do
pry_eval(BasicObject, ":foo", "Pad.obj = _")
Pad.obj.should == :foo
end
it 'should be able to operate inside the BasicObject class' do
pry_eval(BasicObject, ":foo", "Pad.obj = _")
Pad.obj.should == :foo
end
it 'should set an ivar on an object' do
@ -325,9 +319,8 @@ describe Pry do
end
it 'should define a method on the class of an object when performing "def meth;end" inside an immediate value or Numeric' do
# should include float in here, but test fails for some reason
# on 1.8.7, no idea why!
[:test, 0, true, false, nil].each do |val|
[:test, 0, true, false, nil,
(0.0 unless Pry::Helpers::BaseHelpers.jruby?)].each do |val|
pry_eval(val, "def hello; end");
val.class.instance_methods(false).map(&:to_sym).include?(:hello).should == true
end

View file

@ -15,11 +15,9 @@ describe "Pry.run_command" do
out.string.should =~ /hokey_pokey/
end
if !PryTestHelpers.mri18_and_no_real_source_location?
# This is a regression test as 0.9.11 broke this behaviour
it 'can perform a show-source' do
Pry.run_command "show-source drum", :context => @context, :output => out = StringIO.new
out.string.should =~ /roken is dodelijk/
end
# This is a regression test as 0.9.11 broke this behaviour
it 'can perform a show-source' do
Pry.run_command "show-source drum", :context => @context, :output => out = StringIO.new
out.string.should =~ /roken is dodelijk/
end
end

View file

@ -67,7 +67,7 @@ class ReplTester
reset_output
repl_mailbox.push input
wait
Pry.output.string
@pry.output.string
end
# Assert that the current prompt matches the given string or regex.
@ -78,7 +78,7 @@ class ReplTester
# Assert that the most recent output (since the last time input was called)
# matches the given string or regex.
def output(match)
match.should === Pry.output.string.chomp
match.should === @pry.output.string.chomp
end
# Assert that the Pry session ended naturally after the last input.
@ -99,7 +99,7 @@ class ReplTester
private
def reset_output
Pry.output.clear
@pry.output.clear
end
def repl_mailbox

View file

@ -40,17 +40,30 @@ describe "Sticky locals (_file_ and friends)" do
Pry.commands.delete "file-and-dir-test"
end
it 'locals should return last result (_)' do
pry_tester.tap do |t|
lam = t.eval 'lambda { |foo| }'
t.eval('_').should == lam
end
end
it 'locals should return second last result (__)' do
pry_tester.tap do |t|
lam = t.eval 'lambda { |foo| }'
t.eval 'num = 1'
t.eval('__').should == lam
end
end
describe "User defined sticky locals" do
describe "setting as Pry.config option" do
it 'should define a new sticky local for the session (normal value)' do
Pry.config.extra_sticky_locals[:test_local] = :john
o = Object.new
redirect_pry_io(InputTester.new("@value = test_local",
"exit-all")) do
Pry.start(o)
end
o.instance_variable_get(:@value).should == :john
Pry.config.extra_sticky_locals = {}
end