2019-03-10 01:35:36 +02:00
|
|
|
require 'method_source'
|
|
|
|
|
2012-06-19 17:08:59 +02:00
|
|
|
##
|
|
|
|
# Pry is a powerful alternative to the standard IRB shell for Ruby. It
|
|
|
|
# features syntax highlighting, a flexible plugin architecture, runtime
|
|
|
|
# invocation and source and documentation browsing.
|
|
|
|
#
|
|
|
|
# Pry can be started similar to other command line utilities by simply running
|
|
|
|
# the following command:
|
|
|
|
#
|
|
|
|
# pry
|
|
|
|
#
|
|
|
|
# Once inside Pry you can invoke the help message:
|
|
|
|
#
|
|
|
|
# help
|
|
|
|
#
|
|
|
|
# This will show a list of available commands and their usage. For more
|
|
|
|
# information about Pry you can refer to the following resources:
|
|
|
|
#
|
2015-12-19 02:06:51 -03:00
|
|
|
# * http://pryrepl.org/
|
2012-06-19 17:08:59 +02:00
|
|
|
# * https://github.com/pry/pry
|
|
|
|
# * the IRC channel, which is #pry on the Freenode network
|
|
|
|
#
|
2011-01-08 01:18:09 +13:00
|
|
|
|
2018-10-20 01:07:25 +08:00
|
|
|
# rubocop:disable Metrics/ClassLength
|
2013-12-17 18:27:42 +01:00
|
|
|
class Pry
|
2011-08-21 18:22:45 +12:00
|
|
|
attr_accessor :binding_stack
|
2014-01-20 09:08:38 +01:00
|
|
|
attr_accessor :custom_completions
|
2012-12-18 00:45:10 -08:00
|
|
|
attr_accessor :eval_string
|
2013-12-17 18:27:42 +01:00
|
|
|
attr_accessor :backtrace
|
|
|
|
attr_accessor :suppress_output
|
2011-09-01 05:05:21 +12:00
|
|
|
attr_accessor :last_result
|
|
|
|
attr_accessor :last_file
|
|
|
|
attr_accessor :last_dir
|
|
|
|
|
2012-01-07 22:01:15 -08:00
|
|
|
attr_reader :last_exception
|
2012-06-16 00:36:03 +12:00
|
|
|
attr_reader :command_state
|
2012-12-21 01:38:32 -08:00
|
|
|
attr_reader :exit_value
|
2018-10-20 01:07:25 +08:00
|
|
|
|
|
|
|
# @since v0.12.0
|
2018-10-19 22:27:37 +08:00
|
|
|
attr_reader :input_ring
|
2018-10-20 01:07:25 +08:00
|
|
|
|
|
|
|
# @since v0.12.0
|
2018-10-19 22:27:37 +08:00
|
|
|
attr_reader :output_ring
|
2018-10-20 01:07:25 +08:00
|
|
|
|
2013-12-17 18:27:42 +01:00
|
|
|
attr_reader :config
|
2012-12-21 01:38:32 -08:00
|
|
|
|
2013-12-17 18:27:42 +01:00
|
|
|
extend Pry::Config::Convenience
|
2014-06-24 16:30:03 -04:00
|
|
|
config_shortcut(*Pry::Config.shortcuts)
|
2014-02-03 19:28:47 +01:00
|
|
|
EMPTY_COMPLETIONS = [].freeze
|
2012-01-24 01:10:51 +13:00
|
|
|
|
2012-12-27 21:52:58 -08:00
|
|
|
# Create a new {Pry} instance.
|
|
|
|
# @param [Hash] options
|
|
|
|
# @option options [#readline] :input
|
|
|
|
# The object to use for input.
|
|
|
|
# @option options [#puts] :output
|
|
|
|
# The object to use for output.
|
|
|
|
# @option options [Pry::CommandBase] :commands
|
|
|
|
# The object to use for commands.
|
|
|
|
# @option options [Hash] :hooks
|
|
|
|
# The defined hook Procs.
|
2018-11-11 04:20:45 +08:00
|
|
|
# @option options [Pry::Prompt] :prompt
|
2012-12-27 21:52:58 -08:00
|
|
|
# The array of Procs to use for prompts.
|
|
|
|
# @option options [Proc] :print
|
|
|
|
# The Proc to use for printing return values.
|
|
|
|
# @option options [Boolean] :quiet
|
|
|
|
# Omit the `whereami` banner when starting.
|
|
|
|
# @option options [Array<String>] :backtrace
|
|
|
|
# The backtrace of the session's `binding.pry` line, if applicable.
|
|
|
|
# @option options [Object] :target
|
|
|
|
# The initial context for this session.
|
2018-11-04 17:34:24 +08:00
|
|
|
def initialize(options = {})
|
2012-06-16 02:10:56 +03:00
|
|
|
@binding_stack = []
|
|
|
|
@indent = Pry::Indent.new
|
|
|
|
@command_state = {}
|
2012-12-15 16:14:43 -08:00
|
|
|
@eval_string = ""
|
2014-02-02 23:12:56 +01:00
|
|
|
@backtrace = options.delete(:backtrace) || caller
|
2014-04-01 07:04:15 +02:00
|
|
|
target = options.delete(:target)
|
2014-01-20 08:39:35 +01:00
|
|
|
@config = Pry::Config.new
|
2014-01-21 09:26:50 +01:00
|
|
|
config.merge!(options)
|
2014-01-21 09:13:26 +01:00
|
|
|
push_prompt(config.prompt)
|
2018-10-19 22:27:37 +08:00
|
|
|
@input_ring = Pry::Ring.new(config.memory_size)
|
|
|
|
@output_ring = Pry::Ring.new(config.memory_size)
|
2014-03-24 18:37:47 +01:00
|
|
|
@custom_completions = config.command_completions
|
2012-12-19 23:38:34 -08:00
|
|
|
set_last_result nil
|
2018-10-19 22:27:37 +08:00
|
|
|
@input_ring << nil
|
2014-04-01 07:05:54 +02:00
|
|
|
push_initial_binding(target)
|
|
|
|
exec_hook(:when_started, target, options, self)
|
2018-11-11 04:20:45 +08:00
|
|
|
@prompt_warn = false
|
2011-06-01 03:12:29 +12:00
|
|
|
end
|
|
|
|
|
2014-01-21 09:13:26 +01:00
|
|
|
# This is the prompt at the top of the prompt stack.
|
2018-11-11 04:20:45 +08:00
|
|
|
# @return [Pry::Prompt] the current prompt
|
2014-01-21 09:13:26 +01:00
|
|
|
def prompt
|
|
|
|
prompt_stack.last
|
|
|
|
end
|
|
|
|
|
2018-11-11 04:20:45 +08:00
|
|
|
# Sets the Pry prompt.
|
|
|
|
# @param [Pry::Prompt] new_prompt
|
|
|
|
# @return [void]
|
2014-01-21 09:13:26 +01:00
|
|
|
def prompt=(new_prompt)
|
|
|
|
if prompt_stack.empty?
|
|
|
|
push_prompt new_prompt
|
|
|
|
else
|
|
|
|
prompt_stack[-1] = new_prompt
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-12-27 19:56:02 -08:00
|
|
|
# Initialize this instance by pushing its initial context into the binding
|
|
|
|
# stack. If no target is given, start at the top level.
|
2018-11-04 17:34:24 +08:00
|
|
|
def push_initial_binding(target = nil)
|
2012-12-27 19:56:02 -08:00
|
|
|
push_binding(target || Pry.toplevel_binding)
|
2012-12-17 23:42:08 -08:00
|
|
|
end
|
|
|
|
|
2012-02-29 01:36:50 +13:00
|
|
|
# The currently active `Binding`.
|
|
|
|
# @return [Binding] The currently active `Binding` for the session.
|
2012-12-16 17:12:03 -08:00
|
|
|
def current_binding
|
2012-02-29 01:36:50 +13:00
|
|
|
binding_stack.last
|
|
|
|
end
|
2012-12-16 17:12:03 -08:00
|
|
|
alias current_context current_binding # support previous API
|
|
|
|
|
2012-12-23 00:08:40 -08:00
|
|
|
# Push a binding for the given object onto the stack. If this instance is
|
|
|
|
# currently stopped, mark it as usable again.
|
2012-12-16 17:12:03 -08:00
|
|
|
def push_binding(object)
|
2012-12-21 22:06:41 -08:00
|
|
|
@stopped = false
|
2012-12-16 17:12:03 -08:00
|
|
|
binding_stack << Pry.binding_for(object)
|
|
|
|
end
|
2012-02-29 01:36:50 +13:00
|
|
|
|
2014-04-03 02:44:20 +02:00
|
|
|
#
|
2012-12-28 15:19:21 -08:00
|
|
|
# Generate completions.
|
2014-04-03 02:44:20 +02:00
|
|
|
#
|
2015-08-17 15:07:41 +01:00
|
|
|
# @param [String] str
|
2014-04-03 02:44:20 +02:00
|
|
|
# What the user has typed so far
|
|
|
|
#
|
|
|
|
# @return [Array<String>]
|
|
|
|
# Possible completions
|
|
|
|
#
|
|
|
|
def complete(str)
|
2014-02-03 19:28:47 +01:00
|
|
|
return EMPTY_COMPLETIONS unless config.completer
|
2018-10-14 09:44:58 -04:00
|
|
|
|
2012-12-28 15:19:21 -08:00
|
|
|
Pry.critical_section do
|
2014-04-03 02:44:20 +02:00
|
|
|
completer = config.completer.new(config.input, self)
|
2019-03-03 17:37:58 +02:00
|
|
|
completer.call(
|
|
|
|
str,
|
|
|
|
target: current_binding,
|
|
|
|
custom_completions: custom_completions.call.push(*sticky_locals.keys)
|
|
|
|
)
|
2012-12-28 15:19:21 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-04-01 07:37:01 +02:00
|
|
|
#
|
2011-08-31 05:35:41 +12:00
|
|
|
# Injects a local variable into the provided binding.
|
2014-04-01 07:37:01 +02:00
|
|
|
#
|
|
|
|
# @param [String] name
|
|
|
|
# The name of the local to inject.
|
|
|
|
#
|
|
|
|
# @param [Object] value
|
|
|
|
# The value to set the local to.
|
|
|
|
#
|
|
|
|
# @param [Binding] b
|
|
|
|
# The binding to set the local on.
|
|
|
|
#
|
|
|
|
# @return [Object]
|
|
|
|
# The value the local was set to.
|
|
|
|
#
|
2011-08-31 05:35:41 +12:00
|
|
|
def inject_local(name, value, b)
|
2014-04-01 19:20:41 +02:00
|
|
|
value = Proc === value ? value.call : value
|
2014-04-01 07:37:01 +02:00
|
|
|
if b.respond_to?(:local_variable_set)
|
|
|
|
b.local_variable_set name, value
|
|
|
|
else # < 2.1
|
|
|
|
begin
|
|
|
|
Pry.current[:pry_local] = value
|
|
|
|
b.eval "#{name} = ::Pry.current[:pry_local]"
|
|
|
|
ensure
|
|
|
|
Pry.current[:pry_local] = nil
|
|
|
|
end
|
|
|
|
end
|
2011-08-31 05:35:41 +12:00
|
|
|
end
|
|
|
|
|
2014-06-24 16:41:36 -04:00
|
|
|
undef :memory_size if method_defined? :memory_size
|
2011-06-08 00:57:01 +12:00
|
|
|
# @return [Integer] The maximum amount of objects remembered by the inp and
|
|
|
|
# out arrays. Defaults to 100.
|
2011-06-06 17:14:16 +02:00
|
|
|
def memory_size
|
2018-10-19 22:27:37 +08:00
|
|
|
@output_ring.max_size
|
2011-06-06 17:14:16 +02:00
|
|
|
end
|
|
|
|
|
2014-06-24 16:41:36 -04:00
|
|
|
undef :memory_size= if method_defined? :memory_size=
|
2011-06-06 17:14:16 +02:00
|
|
|
def memory_size=(size)
|
2018-10-19 22:27:37 +08:00
|
|
|
@input_ring = Pry::Ring.new(size)
|
|
|
|
@output_ring = Pry::Ring.new(size)
|
2011-06-06 17:14:16 +02:00
|
|
|
end
|
|
|
|
|
2012-12-16 17:12:03 -08:00
|
|
|
# Inject all the sticky locals into the current binding.
|
2012-12-16 16:55:07 -08:00
|
|
|
def inject_sticky_locals!
|
2012-03-04 00:51:11 +13:00
|
|
|
sticky_locals.each_pair do |name, value|
|
2012-12-16 17:12:03 -08:00
|
|
|
inject_local(name, value, current_binding)
|
2011-10-01 17:41:53 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-03-04 00:51:11 +13:00
|
|
|
# Add a sticky local to this Pry instance.
|
|
|
|
# A sticky local is a local that persists between all bindings in a session.
|
|
|
|
# @param [Symbol] name The name of the sticky local.
|
|
|
|
# @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)
|
2014-01-20 16:00:22 +01:00
|
|
|
config.extra_sticky_locals[name] = block
|
2012-03-04 00:51:11 +13:00
|
|
|
end
|
|
|
|
|
|
|
|
def sticky_locals
|
2019-02-25 00:55:58 +02:00
|
|
|
{
|
|
|
|
_in_: input_ring,
|
2018-10-19 22:27:37 +08:00
|
|
|
_out_: output_ring,
|
2014-01-20 08:39:35 +01:00
|
|
|
_pry_: self,
|
2014-03-09 19:39:01 -07:00
|
|
|
_ex_: last_exception && last_exception.wrapped_exception,
|
2014-01-20 08:39:35 +01:00
|
|
|
_file_: last_file,
|
|
|
|
_dir_: last_dir,
|
2014-02-03 22:51:27 +09:00
|
|
|
_: proc { last_result },
|
2018-10-19 22:27:37 +08:00
|
|
|
__: proc { output_ring[-2] }
|
2014-01-20 16:00:22 +01:00
|
|
|
}.merge(config.extra_sticky_locals)
|
2011-09-01 05:05:21 +12:00
|
|
|
end
|
|
|
|
|
2012-12-27 19:56:43 -08:00
|
|
|
# Reset the current eval string. If the user has entered part of a multiline
|
|
|
|
# expression, this discards that input.
|
|
|
|
def reset_eval_string
|
2012-12-20 01:28:04 -08:00
|
|
|
@eval_string = ""
|
2011-03-16 20:02:15 +13:00
|
|
|
end
|
2011-04-07 04:59:09 +12:00
|
|
|
|
2012-12-27 22:06:50 -08:00
|
|
|
# Pass a line of input to Pry.
|
|
|
|
#
|
|
|
|
# This is the equivalent of `Binding#eval` but with extra Pry!
|
2012-12-21 00:40:21 -08:00
|
|
|
#
|
|
|
|
# In particular:
|
2012-12-27 22:06:50 -08:00
|
|
|
# 1. Pry commands will be executed immediately if the line matches.
|
|
|
|
# 2. Partial lines of input will be queued up until a complete expression has
|
|
|
|
# been accepted.
|
2014-03-17 18:23:53 +09:00
|
|
|
# 3. Output is written to `#output` in pretty colours, not returned.
|
2012-12-21 00:40:21 -08:00
|
|
|
#
|
2012-12-27 22:06:50 -08:00
|
|
|
# Once this method has raised an exception or returned false, this instance
|
|
|
|
# is no longer usable. {#exit_value} will return the session's breakout
|
|
|
|
# value if applicable.
|
2012-12-21 00:40:21 -08:00
|
|
|
#
|
2012-12-27 22:06:50 -08:00
|
|
|
# @param [String?] line The line of input; `nil` if the user types `<Ctrl-D>`
|
2012-12-28 11:18:29 -08:00
|
|
|
# @option options [Boolean] :generated Whether this line was generated automatically.
|
|
|
|
# Generated lines are not stored in history.
|
2012-12-27 22:06:50 -08:00
|
|
|
# @return [Boolean] Is Pry ready to accept more input?
|
|
|
|
# @raise [Exception] If the user uses the `raise-up` command, this method
|
|
|
|
# will raise that exception.
|
2018-11-04 17:34:24 +08:00
|
|
|
def eval(line, options = {})
|
2012-12-21 00:40:21 -08:00
|
|
|
return false if @stopped
|
|
|
|
|
2012-12-21 01:38:32 -08:00
|
|
|
exit_value = nil
|
2012-03-07 21:54:19 -08:00
|
|
|
exception = catch(:raise_up) do
|
2012-12-21 01:38:32 -08:00
|
|
|
exit_value = catch(:breakout) do
|
2012-12-28 11:18:29 -08:00
|
|
|
handle_line(line, options)
|
2012-12-28 10:00:33 -08:00
|
|
|
# We use 'return !@stopped' here instead of 'return true' so that if
|
|
|
|
# handle_line has stopped this pry instance (e.g. by opening _pry_.repl and
|
|
|
|
# then popping all the bindings) we still exit immediately.
|
|
|
|
return !@stopped
|
2010-12-26 02:59:37 +13:00
|
|
|
end
|
2012-03-07 21:54:19 -08:00
|
|
|
exception = false
|
2010-12-26 02:59:37 +13:00
|
|
|
end
|
|
|
|
|
2012-12-21 01:38:32 -08:00
|
|
|
@stopped = true
|
|
|
|
@exit_value = exit_value
|
2012-03-07 21:54:19 -08:00
|
|
|
|
2012-12-21 01:38:32 -08:00
|
|
|
# TODO: make this configurable?
|
|
|
|
raise exception if exception
|
2018-10-14 09:44:58 -04:00
|
|
|
|
2019-03-02 13:32:04 +02:00
|
|
|
false
|
2010-12-26 02:59:37 +13:00
|
|
|
end
|
2011-01-14 01:35:46 +11:00
|
|
|
|
2012-12-28 11:18:29 -08:00
|
|
|
def handle_line(line, options)
|
2012-12-20 23:58:58 -08:00
|
|
|
if line.nil?
|
2014-02-03 02:26:15 +01:00
|
|
|
config.control_d_handler.call(@eval_string, self)
|
2012-12-20 23:58:58 -08:00
|
|
|
return
|
2012-11-13 21:59:59 -08:00
|
|
|
end
|
2010-12-26 02:59:37 +13:00
|
|
|
|
2012-12-28 11:18:29 -08:00
|
|
|
ensure_correct_encoding!(line)
|
|
|
|
Pry.history << line unless options[:generated]
|
2011-01-08 01:18:09 +13:00
|
|
|
|
2012-12-20 01:28:04 -08:00
|
|
|
@suppress_output = false
|
|
|
|
inject_sticky_locals!
|
2012-12-16 14:07:31 -08:00
|
|
|
begin
|
2019-03-02 12:00:35 +02:00
|
|
|
unless process_command_safely(line)
|
2013-02-01 07:25:22 +02:00
|
|
|
@eval_string << "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
|
2012-12-16 14:07:31 -08:00
|
|
|
end
|
|
|
|
rescue RescuableException => e
|
|
|
|
self.last_exception = e
|
|
|
|
result = e
|
2011-04-16 23:17:30 +02:00
|
|
|
|
2012-12-16 14:07:31 -08:00
|
|
|
Pry.critical_section do
|
|
|
|
show_result(result)
|
2012-12-15 16:14:43 -08:00
|
|
|
end
|
2012-12-16 14:07:31 -08:00
|
|
|
return
|
2012-12-15 16:14:43 -08:00
|
|
|
end
|
2011-05-15 12:08:59 +02:00
|
|
|
|
2012-12-20 01:28:04 -08:00
|
|
|
# This hook is supposed to be executed after each line of ruby code
|
|
|
|
# has been read (regardless of whether eval_string is yet a complete expression)
|
|
|
|
exec_hook :after_read, eval_string, self
|
2010-12-26 02:59:37 +13:00
|
|
|
|
2012-12-15 16:14:43 -08:00
|
|
|
begin
|
|
|
|
complete_expr = Pry::Code.complete_expression?(@eval_string)
|
|
|
|
rescue SyntaxError => e
|
|
|
|
output.puts "SyntaxError: #{e.message.sub(/.*syntax error, */m, '')}"
|
2012-12-27 19:56:43 -08:00
|
|
|
reset_eval_string
|
2012-12-15 16:14:43 -08:00
|
|
|
end
|
2011-01-10 00:51:45 +13:00
|
|
|
|
2012-12-15 16:14:43 -08:00
|
|
|
if complete_expr
|
2019-03-03 17:37:58 +02:00
|
|
|
if @eval_string =~ /;\Z/ || @eval_string.empty? || @eval_string =~ /\A *#.*\n\z/
|
|
|
|
@suppress_output = true
|
|
|
|
end
|
2011-05-25 00:34:55 +12:00
|
|
|
|
2013-03-26 20:47:26 +08:00
|
|
|
# A bug in jruby makes java.lang.Exception not rescued by
|
|
|
|
# `rescue Pry::RescuableException` clause.
|
|
|
|
#
|
|
|
|
# * https://github.com/pry/pry/issues/854
|
|
|
|
# * https://jira.codehaus.org/browse/JRUBY-7100
|
|
|
|
#
|
|
|
|
# Until that gets fixed upstream, treat java.lang.Exception
|
|
|
|
# as an additional exception to be rescued explicitly.
|
|
|
|
#
|
|
|
|
# This workaround has a side effect: java exceptions specified
|
2018-11-11 01:34:09 +09:00
|
|
|
# in `Pry.config.unrescued_exceptions` are ignored.
|
2013-03-26 20:47:26 +08:00
|
|
|
jruby_exceptions = []
|
2019-03-02 02:03:35 +02:00
|
|
|
jruby_exceptions << Java::JavaLang::Exception if Helpers::Platform.jruby?
|
2013-03-26 20:47:26 +08:00
|
|
|
|
2012-01-12 23:21:21 -08:00
|
|
|
begin
|
2012-12-23 00:05:18 -08:00
|
|
|
# Reset eval string, in case we're evaluating Ruby that does something
|
|
|
|
# like open a nested REPL on this instance.
|
|
|
|
eval_string = @eval_string
|
2012-12-27 19:56:43 -08:00
|
|
|
reset_eval_string
|
2012-12-23 00:05:18 -08:00
|
|
|
|
|
|
|
result = evaluate_ruby(eval_string)
|
2013-03-26 20:47:26 +08:00
|
|
|
rescue RescuableException, *jruby_exceptions => e
|
2013-03-26 20:49:40 +08:00
|
|
|
# Eliminate following warning:
|
|
|
|
# warning: singleton on non-persistent Java type X
|
|
|
|
# (http://wiki.jruby.org/Persistence)
|
2019-03-03 17:37:58 +02:00
|
|
|
if Helpers::Platform.jruby? && e.class.respond_to?('__persistent__')
|
|
|
|
e.class.__persistent__ = true
|
|
|
|
end
|
2012-12-15 16:14:43 -08:00
|
|
|
self.last_exception = e
|
|
|
|
result = e
|
2012-01-12 23:21:21 -08:00
|
|
|
end
|
2011-04-08 02:13:16 +12:00
|
|
|
|
2012-12-15 16:14:43 -08:00
|
|
|
Pry.critical_section do
|
|
|
|
show_result(result)
|
2012-12-15 14:29:31 -08:00
|
|
|
end
|
2012-10-20 22:54:58 -07:00
|
|
|
end
|
2011-04-16 23:17:30 +02:00
|
|
|
|
2012-12-20 01:28:04 -08:00
|
|
|
throw(:breakout) if current_binding.nil?
|
2011-04-15 15:58:29 +12:00
|
|
|
end
|
2012-12-28 11:18:29 -08:00
|
|
|
private :handle_line
|
2011-04-15 15:58:29 +12:00
|
|
|
|
2013-04-19 19:24:21 -05:00
|
|
|
# Potentially deprecated — Use `Pry::REPL.new(pry, :target => target).start`
|
|
|
|
# (If nested sessions are going to exist, this method is fine, but a goal is
|
|
|
|
# to come up with an alternative to nested sessions altogether.)
|
2012-12-23 00:08:40 -08:00
|
|
|
def repl(target = nil)
|
2018-10-13 03:09:29 +08:00
|
|
|
Pry::REPL.new(self, target: target).start
|
2011-04-15 15:58:29 +12:00
|
|
|
end
|
|
|
|
|
2012-12-16 16:55:07 -08:00
|
|
|
def evaluate_ruby(code)
|
|
|
|
inject_sticky_locals!
|
2012-08-07 21:02:54 -07:00
|
|
|
exec_hook :before_eval, code, self
|
2012-07-23 04:03:05 -04:00
|
|
|
|
2012-12-16 17:12:03 -08:00
|
|
|
result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
|
2012-12-16 17:27:21 -08:00
|
|
|
set_last_result(result, code)
|
2012-07-25 00:13:32 -04:00
|
|
|
ensure
|
|
|
|
update_input_history(code)
|
2012-08-07 21:02:54 -07:00
|
|
|
exec_hook :after_eval, result, self
|
2012-07-23 04:03:05 -04:00
|
|
|
end
|
|
|
|
|
2011-05-30 03:46:25 +12:00
|
|
|
# Output the result or pass to an exception handler (if result is an exception).
|
2011-04-16 16:47:48 +12:00
|
|
|
def show_result(result)
|
2011-04-16 23:17:30 +02:00
|
|
|
if last_result_is_exception?
|
2012-07-12 23:13:13 +12:00
|
|
|
exception_handler.call(output, result, self)
|
2012-08-07 21:03:36 -07:00
|
|
|
elsif should_print?
|
2014-02-05 22:29:25 +09:00
|
|
|
print.call(output, result, self)
|
2011-04-16 23:17:30 +02:00
|
|
|
end
|
2011-08-27 01:58:53 -07:00
|
|
|
rescue RescuableException => e
|
2011-08-23 00:54:58 -07:00
|
|
|
# Being uber-paranoid here, given that this exception arose because we couldn't
|
|
|
|
# serialize something in the user's program, let's not assume we can serialize
|
|
|
|
# the exception either.
|
|
|
|
begin
|
2016-02-26 13:49:27 +00:00
|
|
|
output.puts "(pry) output error: #{e.inspect}\n#{e.backtrace.join("\n")}"
|
2011-08-27 01:58:53 -07:00
|
|
|
rescue RescuableException => e
|
2011-08-23 00:54:58 -07:00
|
|
|
if last_result_is_exception?
|
2011-09-14 15:48:20 -07:00
|
|
|
output.puts "(pry) output error: failed to show exception"
|
2011-08-23 00:54:58 -07:00
|
|
|
else
|
2011-09-14 15:48:20 -07:00
|
|
|
output.puts "(pry) output error: failed to show result"
|
2011-08-23 00:54:58 -07:00
|
|
|
end
|
|
|
|
end
|
2013-02-10 23:38:01 -06:00
|
|
|
ensure
|
|
|
|
output.flush if output.respond_to?(:flush)
|
2011-04-15 15:58:29 +12:00
|
|
|
end
|
2011-04-08 02:13:16 +12:00
|
|
|
|
2012-12-27 21:52:58 -08:00
|
|
|
# Force `eval_string` into the encoding of `val`. [Issue #284]
|
2012-12-18 00:30:18 -08:00
|
|
|
def ensure_correct_encoding!(val)
|
|
|
|
if @eval_string.empty? &&
|
2019-02-25 02:16:10 +02:00
|
|
|
val.respond_to?(:encoding) &&
|
|
|
|
val.encoding != @eval_string.encoding
|
2012-12-18 00:30:18 -08:00
|
|
|
@eval_string.force_encoding(val.encoding)
|
2011-04-01 02:14:04 +13:00
|
|
|
end
|
|
|
|
end
|
2012-12-09 13:51:52 -08:00
|
|
|
private :ensure_correct_encoding!
|
2011-01-14 01:35:46 +11:00
|
|
|
|
2011-11-19 18:16:23 -08:00
|
|
|
# If the given line is a valid command, process it in the context of the
|
2012-12-27 21:52:58 -08:00
|
|
|
# current `eval_string` and binding.
|
2011-04-01 02:14:04 +13:00
|
|
|
# @param [String] val The line to process.
|
2011-11-19 18:16:23 -08:00
|
|
|
# @return [Boolean] `true` if `val` is a command, `false` otherwise
|
2012-12-18 00:30:18 -08:00
|
|
|
def process_command(val)
|
2015-03-08 08:41:48 +02:00
|
|
|
val = val.lstrip if /^\s\S/ !~ val
|
2012-08-19 00:24:04 -07:00
|
|
|
val = val.chomp
|
2019-02-24 19:39:14 +02:00
|
|
|
result = commands.process_line(
|
|
|
|
val,
|
2018-10-13 03:09:29 +08:00
|
|
|
target: current_binding,
|
|
|
|
output: output,
|
|
|
|
eval_string: @eval_string,
|
|
|
|
pry_instance: self,
|
|
|
|
hooks: hooks
|
2012-12-16 17:27:21 -08:00
|
|
|
)
|
2011-09-06 04:12:53 +12:00
|
|
|
|
|
|
|
# set a temporary (just so we can inject the value we want into eval_string)
|
2013-01-15 23:29:23 +01:00
|
|
|
Pry.current[:pry_cmd_result] = result
|
2011-09-05 01:50:27 +12:00
|
|
|
|
|
|
|
# note that `result` wraps the result of command processing; if a
|
|
|
|
# command was matched and invoked then `result.command?` returns true,
|
|
|
|
# otherwise it returns false.
|
2011-11-19 18:16:23 -08:00
|
|
|
if result.command?
|
2019-03-02 12:00:35 +02:00
|
|
|
unless result.void_command?
|
2011-11-19 18:16:23 -08:00
|
|
|
# the command that was invoked was non-void (had a return value) and so we make
|
|
|
|
# the value of the current expression equal to the return value
|
|
|
|
# of the command.
|
2013-01-17 23:56:07 -08:00
|
|
|
@eval_string.replace "::Pry.current[:pry_cmd_result].retval\n"
|
2011-11-19 18:16:23 -08:00
|
|
|
end
|
|
|
|
true
|
2011-04-01 02:14:04 +13:00
|
|
|
else
|
2011-11-19 18:16:23 -08:00
|
|
|
false
|
2010-12-26 02:59:37 +13:00
|
|
|
end
|
|
|
|
end
|
2011-01-14 01:35:46 +11:00
|
|
|
|
2014-03-17 18:23:53 +09:00
|
|
|
# Same as process_command, but outputs exceptions to `#output` instead of
|
2012-12-27 21:52:58 -08:00
|
|
|
# raising.
|
2012-12-09 13:51:52 -08:00
|
|
|
# @param [String] val The line to process.
|
|
|
|
# @return [Boolean] `true` if `val` is a command, `false` otherwise
|
2012-12-18 00:30:18 -08:00
|
|
|
def process_command_safely(val)
|
|
|
|
process_command(val)
|
2019-03-03 17:37:58 +02:00
|
|
|
rescue CommandError,
|
|
|
|
Pry::Slop::InvalidOptionError,
|
|
|
|
MethodSource::SourceNotFoundError => e
|
2013-01-20 03:50:38 +01:00
|
|
|
Pry.last_internal_error = e
|
2012-12-09 13:51:52 -08:00
|
|
|
output.puts "Error: #{e.message}"
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2011-09-11 04:41:51 +12:00
|
|
|
# Run the specified command.
|
2011-10-28 00:10:12 +13:00
|
|
|
# @param [String] val The command (and its params) to execute.
|
2011-12-31 11:50:04 +00:00
|
|
|
# @return [Pry::Command::VOID_VALUE]
|
2011-09-11 04:41:51 +12:00
|
|
|
# @example
|
|
|
|
# pry_instance.run_command("ls -m")
|
2012-12-18 00:30:18 -08:00
|
|
|
def run_command(val)
|
2019-02-24 19:39:14 +02:00
|
|
|
commands.process_line(
|
|
|
|
val,
|
2018-10-13 03:09:29 +08:00
|
|
|
eval_string: @eval_string,
|
|
|
|
target: current_binding,
|
|
|
|
pry_instance: self,
|
|
|
|
output: output
|
2012-01-03 00:04:47 +00:00
|
|
|
)
|
2011-12-31 11:50:04 +00:00
|
|
|
Pry::Command::VOID_VALUE
|
2011-09-11 04:41:51 +12:00
|
|
|
end
|
|
|
|
|
2012-01-14 00:33:36 -08:00
|
|
|
# Execute the specified hook.
|
|
|
|
# @param [Symbol] name The hook name to execute
|
|
|
|
# @param [*Object] args The arguments to pass to the hook
|
|
|
|
# @return [Object, Exception] The return value of the hook or the exception raised
|
|
|
|
#
|
|
|
|
# If executing a hook raises an exception, we log that and then continue sucessfully.
|
|
|
|
# To debug such errors, use the global variable $pry_hook_error, which is set as a
|
|
|
|
# result.
|
|
|
|
def exec_hook(name, *args, &block)
|
|
|
|
e_before = hooks.errors.size
|
2012-01-16 17:42:21 -08:00
|
|
|
hooks.exec_hook(name, *args, &block).tap do
|
|
|
|
hooks.errors[e_before..-1].each do |e|
|
|
|
|
output.puts "#{name} hook failed: #{e.class}: #{e.message}"
|
2019-03-02 16:43:53 +02:00
|
|
|
output.puts e.backtrace.first.to_s
|
2012-01-16 17:42:21 -08:00
|
|
|
output.puts "(see _pry_.hooks.errors to debug)"
|
|
|
|
end
|
2012-01-14 00:33:36 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-03-14 23:55:22 +13:00
|
|
|
# Set the last result of an eval.
|
2011-04-01 02:14:04 +13:00
|
|
|
# This method should not need to be invoked directly.
|
2011-03-14 23:55:22 +13:00
|
|
|
# @param [Object] result The result.
|
2012-01-12 23:43:06 -08:00
|
|
|
# @param [String] code The code that was run.
|
2018-11-04 17:34:24 +08:00
|
|
|
def set_last_result(result, code = "")
|
2011-08-07 01:19:28 -07:00
|
|
|
@last_result_is_exception = false
|
2018-10-19 22:27:37 +08:00
|
|
|
@output_ring << result
|
2011-08-07 01:19:28 -07:00
|
|
|
|
2012-01-12 23:43:06 -08:00
|
|
|
self.last_result = result unless code =~ /\A\s*\z/
|
2011-03-14 23:55:22 +13:00
|
|
|
end
|
|
|
|
|
2014-03-10 01:28:12 +01:00
|
|
|
#
|
2011-03-14 23:55:22 +13:00
|
|
|
# Set the last exception for a session.
|
2014-03-10 01:28:12 +01:00
|
|
|
#
|
|
|
|
# @param [Exception] e
|
|
|
|
# the last exception.
|
|
|
|
#
|
|
|
|
def last_exception=(e)
|
|
|
|
last_exception = Pry::LastException.new(e)
|
2011-08-07 01:19:28 -07:00
|
|
|
@last_result_is_exception = true
|
2018-10-19 22:27:37 +08:00
|
|
|
@output_ring << last_exception
|
2014-03-10 01:28:12 +01:00
|
|
|
@last_exception = last_exception
|
2011-03-14 23:55:22 +13:00
|
|
|
end
|
|
|
|
|
2011-08-07 01:19:28 -07:00
|
|
|
# Update Pry's internal state after evalling code.
|
|
|
|
# This method should not need to be invoked directly.
|
2011-08-11 23:35:04 +12:00
|
|
|
# @param [String] code The code we just eval'd
|
2011-08-07 01:19:28 -07:00
|
|
|
def update_input_history(code)
|
2018-10-19 22:27:37 +08:00
|
|
|
# Always push to the @input_ring as the @output_ring is always pushed to.
|
|
|
|
@input_ring << code
|
2011-08-07 01:19:28 -07:00
|
|
|
if code
|
|
|
|
Pry.line_buffer.push(*code.each_line)
|
2014-07-07 16:07:13 -04:00
|
|
|
Pry.current_line += code.lines.count
|
2011-08-07 01:19:28 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2011-04-16 23:17:30 +02:00
|
|
|
# @return [Boolean] True if the last result is an exception that was raised,
|
|
|
|
# as opposed to simply an instance of Exception (like the result of
|
|
|
|
# Exception.new)
|
|
|
|
def last_result_is_exception?
|
|
|
|
@last_result_is_exception
|
|
|
|
end
|
|
|
|
|
2011-04-11 11:10:05 +12:00
|
|
|
# Whether the print proc should be invoked.
|
2012-08-07 21:03:36 -07:00
|
|
|
# Currently only invoked if the output is not suppressed.
|
2011-04-11 11:10:05 +12:00
|
|
|
# @return [Boolean] Whether the print proc should be invoked.
|
2011-04-18 16:47:35 +12:00
|
|
|
def should_print?
|
2012-08-07 21:03:36 -07:00
|
|
|
!@suppress_output
|
2011-04-11 11:10:05 +12:00
|
|
|
end
|
2011-04-16 23:17:30 +02:00
|
|
|
|
2010-12-28 16:56:23 +13:00
|
|
|
# Returns the appropriate prompt to use.
|
|
|
|
# @return [String] The prompt.
|
2012-12-18 00:30:18 -08:00
|
|
|
def select_prompt
|
2012-12-16 17:27:21 -08:00
|
|
|
object = current_binding.eval('self')
|
2018-10-20 00:21:07 +08:00
|
|
|
open_token = @indent.open_delimiters.last || @indent.stack.last
|
2012-07-12 23:13:13 +12:00
|
|
|
|
2019-02-25 00:40:20 +02:00
|
|
|
c = Pry::Config.assign(
|
|
|
|
object: object,
|
|
|
|
nesting_level: binding_stack.size - 1,
|
|
|
|
open_token: open_token,
|
|
|
|
session_line: Pry.history.session_line_count + 1,
|
|
|
|
history_line: Pry.history.history_line_count + 1,
|
|
|
|
expr_number: input_ring.count,
|
|
|
|
_pry_: self,
|
|
|
|
binding_stack: binding_stack,
|
|
|
|
input_ring: input_ring,
|
|
|
|
eval_string: @eval_string,
|
|
|
|
cont: !@eval_string.empty?
|
|
|
|
)
|
2012-07-12 23:13:13 +12:00
|
|
|
|
2012-11-13 21:59:59 -08:00
|
|
|
Pry.critical_section do
|
2018-11-11 04:20:45 +08:00
|
|
|
# If input buffer is empty, then use normal prompt. Otherwise use the wait
|
|
|
|
# prompt (indicating multi-line expression).
|
|
|
|
if prompt.is_a?(Pry::Prompt)
|
|
|
|
prompt_proc = eval_string.empty? ? prompt.wait_proc : prompt.incomplete_proc
|
|
|
|
return prompt_proc.call(c.object, c.nesting_level, c._pry_)
|
|
|
|
end
|
|
|
|
|
|
|
|
unless @prompt_warn
|
|
|
|
@prompt_warn = true
|
|
|
|
output.warn(
|
|
|
|
"warning: setting prompt with help of " \
|
|
|
|
"`Pry.config.prompt = [proc {}, proc {}]` is deprecated. " \
|
|
|
|
"Use Pry::Prompt API instead"
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2012-11-13 21:59:59 -08:00
|
|
|
# If input buffer is empty then use normal prompt
|
|
|
|
if eval_string.empty?
|
|
|
|
generate_prompt(Array(prompt).first, c)
|
|
|
|
# Otherwise use the wait prompt (indicating multi-line expression)
|
|
|
|
else
|
|
|
|
generate_prompt(Array(prompt).last, c)
|
|
|
|
end
|
2010-12-26 02:59:37 +13:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-07-13 03:52:55 +12:00
|
|
|
def generate_prompt(prompt_proc, conf)
|
|
|
|
if prompt_proc.arity == 1
|
|
|
|
prompt_proc.call(conf)
|
|
|
|
else
|
|
|
|
prompt_proc.call(conf.object, conf.nesting_level, conf._pry_)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
private :generate_prompt
|
|
|
|
|
2011-04-30 16:16:20 -05:00
|
|
|
# the array that the prompt stack is stored in
|
|
|
|
def prompt_stack
|
2019-03-01 01:31:34 +02:00
|
|
|
@prompt_stack ||= []
|
2011-04-30 16:16:20 -05:00
|
|
|
end
|
|
|
|
private :prompt_stack
|
|
|
|
|
|
|
|
# Pushes the current prompt onto a stack that it can be restored from later.
|
|
|
|
# Use this if you wish to temporarily change the prompt.
|
2018-11-11 04:20:45 +08:00
|
|
|
#
|
2011-04-30 16:16:20 -05:00
|
|
|
# @example
|
2018-11-11 04:20:45 +08:00
|
|
|
# push_prompt(Pry::Prompt[:my_prompt])
|
|
|
|
#
|
|
|
|
# @param [Pry::Prompt] new_prompt
|
|
|
|
# @return [Pry::Prompt] new_prompt
|
2011-04-30 16:16:20 -05:00
|
|
|
def push_prompt(new_prompt)
|
|
|
|
prompt_stack.push new_prompt
|
|
|
|
end
|
|
|
|
|
2018-11-11 04:20:45 +08:00
|
|
|
# Pops the current prompt off of the prompt stack. If the prompt you are
|
|
|
|
# popping is the last prompt, it will not be popped. Use this to restore the
|
|
|
|
# previous prompt.
|
|
|
|
#
|
2011-04-30 16:16:20 -05:00
|
|
|
# @example
|
2018-11-11 04:20:45 +08:00
|
|
|
# pry = Pry.new(prompt: Pry::Prompt[:my_prompt1])
|
|
|
|
# pry.push_prompt(Pry::Prompt[:my_prompt2])
|
2011-04-30 16:16:20 -05:00
|
|
|
# pry.pop_prompt # => prompt2
|
|
|
|
# pry.pop_prompt # => prompt1
|
|
|
|
# pry.pop_prompt # => prompt1
|
2018-11-11 04:20:45 +08:00
|
|
|
#
|
|
|
|
# @return [Pry::Prompt] the prompt being popped
|
2011-04-30 16:16:20 -05:00
|
|
|
def pop_prompt
|
2011-05-19 18:18:21 +01:00
|
|
|
prompt_stack.size > 1 ? prompt_stack.pop : prompt
|
2011-04-30 16:16:20 -05:00
|
|
|
end
|
|
|
|
|
2014-06-24 16:41:36 -04:00
|
|
|
undef :pager if method_defined? :pager
|
2014-04-30 02:08:29 -07:00
|
|
|
# Returns the currently configured pager
|
|
|
|
# @example
|
|
|
|
# _pry_.pager.page text
|
|
|
|
def pager
|
|
|
|
Pry::Pager.new(self)
|
|
|
|
end
|
|
|
|
|
2014-06-24 16:41:36 -04:00
|
|
|
undef :output if method_defined? :output
|
2014-05-01 01:10:10 -07:00
|
|
|
# Returns an output device
|
|
|
|
# @example
|
|
|
|
# _pry_.output.puts "ohai!"
|
|
|
|
def output
|
|
|
|
Pry::Output.new(self)
|
|
|
|
end
|
|
|
|
|
2012-03-17 23:45:42 -07:00
|
|
|
# Raise an exception out of Pry.
|
|
|
|
#
|
|
|
|
# See Kernel#raise for documentation of parameters.
|
|
|
|
# See rb_make_exception for the inbuilt implementation.
|
|
|
|
#
|
|
|
|
# This is necessary so that the raise-up command can tell the
|
|
|
|
# difference between an exception the user has decided to raise,
|
|
|
|
# and a mistake in specifying that exception.
|
|
|
|
#
|
|
|
|
# (i.e. raise-up RunThymeError.new should not be the same as
|
|
|
|
# raise-up NameError, "unititialized constant RunThymeError")
|
|
|
|
#
|
|
|
|
def raise_up_common(force, *args)
|
|
|
|
exception = if args == []
|
|
|
|
last_exception || RuntimeError.new
|
|
|
|
elsif args.length == 1 && args.first.is_a?(String)
|
|
|
|
RuntimeError.new(args.first)
|
|
|
|
elsif args.length > 3
|
|
|
|
raise ArgumentError, "wrong number of arguments"
|
|
|
|
elsif !args.first.respond_to?(:exception)
|
|
|
|
raise TypeError, "exception class/object expected"
|
|
|
|
elsif args.length === 1
|
|
|
|
args.first.exception
|
|
|
|
else
|
|
|
|
args.first.exception(args[1])
|
|
|
|
end
|
|
|
|
|
|
|
|
raise TypeError, "exception object expected" unless exception.is_a? Exception
|
|
|
|
|
|
|
|
exception.set_backtrace(args.length === 3 ? args[2] : caller(1))
|
|
|
|
|
|
|
|
if force || binding_stack.one?
|
|
|
|
binding_stack.clear
|
|
|
|
throw :raise_up, exception
|
|
|
|
else
|
|
|
|
binding_stack.pop
|
|
|
|
raise exception
|
|
|
|
end
|
|
|
|
end
|
2018-10-14 14:23:34 +08:00
|
|
|
|
2019-03-02 15:35:35 +02:00
|
|
|
def raise_up(*args)
|
|
|
|
raise_up_common(false, *args)
|
|
|
|
end
|
2018-10-14 14:23:34 +08:00
|
|
|
|
2019-03-02 15:35:35 +02:00
|
|
|
def raise_up!(*args)
|
|
|
|
raise_up_common(true, *args)
|
|
|
|
end
|
2014-07-06 16:27:46 -07:00
|
|
|
|
|
|
|
# Convenience accessor for the `quiet` config key.
|
|
|
|
# @return [Boolean]
|
|
|
|
def quiet?
|
|
|
|
config.quiet
|
|
|
|
end
|
2010-12-26 02:59:37 +13:00
|
|
|
end
|
2018-10-20 01:07:25 +08:00
|
|
|
# rubocop:enable Metrics/ClassLength
|