diff --git a/lib/pry/commands.rb b/lib/pry/commands.rb index 5dc15b3b..a0c47efe 100644 --- a/lib/pry/commands.rb +++ b/lib/pry/commands.rb @@ -1,4 +1,11 @@ class Pry + + # Default commands used by Pry. + # @notes + # If you plan to replace the default Commands class with a custom + # one then it must have a `commands` method that returns a Hash. + # The Hash should be set up so that the key is the command String + # (or Regexp) class Commands attr_accessor :out @@ -10,23 +17,28 @@ class Pry @commands ||= { "!" => proc do |opts| out.puts "Refreshed REPL" + opts[:val].clear opts[:eval_string].clear end, + "!pry" => proc do |opts| + Pry.start(opts[:target]) + opts[:val].clear + end, ["exit_program", "quit_program"] => proc do exit end, /^help\s*(.+)?/ => proc do |opts| param = opts[:captures].first self.show_help(param) - opts[:eval_string].clear + opts[:val].clear end, "nesting" => proc do |opts| self.show_nesting(opts[:nesting]) - opts[:eval_string].clear + opts[:val].clear end, "status" => proc do |opts| self.show_status(opts[:nesting], opts[:target]) - opts[:eval_string].clear + opts[:val].clear end, "exit_all" => proc do throw(:breakout, 0) @@ -36,39 +48,39 @@ class Pry end, "ls" => proc do |opts| out.puts "#{opts[:target].eval('Pry.view(local_variables + instance_variables)')}" - opts[:eval_string].clear + opts[:val].clear end, /^cat\s+(.+)/ => proc do |opts| obj = opts[:captures].first out.puts opts[:target].eval("#{obj}.inspect") - opts[:eval_string].clear + opts[:val].clear end, /^cd\s+(.+)/ => proc do |opts| obj = opts[:captures].first opts[:target].eval("#{obj}.pry") - opts[:eval_string].clear + opts[:val].clear end, /^show_doc\s*(.+)/ => proc do |opts| meth_name = opts[:captures].first doc = opts[:target].eval("method(:#{meth_name})").comment out.puts doc - opts[:eval_string].clear + opts[:val].clear end, /^show_idoc\s*(.+)/ => proc do |opts| meth_name = opts[:captures].first doc = opts[:target].eval("instance_method(:#{meth_name})").comment - opts[:eval_string].clear + opts[:val].clear end, /^show_method\s*(.+)/ => proc do |opts| meth_name = opts[:captures].first code = opts[:target].eval("method(:#{meth_name})").source out.puts code - opts[:eval_string].clear + opts[:val].clear end, /^show_imethod\s*(.+)/ => proc do |opts| meth_name = opts[:captures].first code = opts[:target].eval("instance_method(:#{meth_name})").source - opts[:eval_string].clear + opts[:val].clear end, /^jump_to\s*(\d*)/ => proc do |opts| break_level = opts[:captures].first.to_i @@ -77,22 +89,22 @@ class Pry case break_level when nesting.level out.puts "Already at nesting level #{nesting.level}" - opts[:eval_string].clear + opts[:val].clear when (0...nesting.level) throw(:breakout, break_level + 1) else max_nest_level = nesting.level - 1 out.puts "Invalid nest level. Must be between 0 and #{max_nest_level}. Got #{break_level}." - opts[:eval_string].clear + opts[:val].clear end end, "ls_methods" => proc do |opts| out.puts "#{Pry.view(opts[:target].eval('public_methods(false)'))}" - opts[:eval_string].clear + opts[:val].clear end, "ls_imethods" => proc do |opts| out.puts "#{Pry.view(opts[:target].eval('public_instance_methods(false)'))}" - opts[:eval_string].clear + opts[:val].clear end } end @@ -100,6 +112,7 @@ class Pry def command_info @command_info ||= { "!" => "Refresh the REPL.", + "!pry" => "Start a Pry session on current self; this even works mid-expression.", ["exit_program", "quit_program"] => "end the current program.", "help" => "This menu.", "nesting" => "Show nesting information.", diff --git a/lib/pry/core_extensions.rb b/lib/pry/core_extensions.rb index 919f9342..fb8898bd 100644 --- a/lib/pry/core_extensions.rb +++ b/lib/pry/core_extensions.rb @@ -1,9 +1,28 @@ class Pry module ObjectExtensions + + # Start a Pry REPL. + # This method differs from `Pry.start` in that it does not + # support an options hash. Also, when no parameter is provided, the Pry + # session will start on the implied receiver rather than on + # top-level (as in the case of `Pry.start`). + # It has two forms of invocation. In the first form no parameter + # should be provided and it will start a pry session on the + # receiver. In the second form it should be invoked without an + # explicit receiver and one parameter; this will start a Pry + # session on the parameter. + # @param [Object, Binding] target The receiver of the Pry session. + # @example First form + # "dummy".pry + # @example Second form + # pry "dummy" + # @example Start a Pry session on current self (whatever that is) + # pry def pry(target=self) Pry.start(target) end + # Return a binding object for the receiver. def __binding__ if is_a?(Module) return class_eval "binding" diff --git a/lib/pry/pry_class.rb b/lib/pry/pry_class.rb index 11163263..350e5829 100644 --- a/lib/pry/pry_class.rb +++ b/lib/pry/pry_class.rb @@ -19,45 +19,39 @@ class Pry # @return [Pry] The active Pry instance. attr_accessor :active_instance - # Set/Get the object to use for input by default by all Pry instances. - # (see input.rb) + # Get/Set the object to use for input by default by all Pry instances. # @return [#read] The object to use for input by default by all # Pry instances. attr_accessor :input - # Set/Get the object to use for output by default by all Pry instances. - # (see: output.rb) + # Get/Set the object to use for output by default by all Pry instances. # @return [#puts] The object to use for output by default by all # Pry instances. attr_accessor :output - # Set/Get the object to use for commands by default by all Pry instances. - # (see commands.rb) + # Get/Set the object to use for commands by default by all Pry instances. # @return [#commands] The object to use for commands by default by all # Pry instances. attr_accessor :commands - # Set/Get the Proc to use for printing by default by all Pry + # Get/Set the Proc to use for printing by default by all Pry # instances. - # This is the 'print' componenent of the REPL. - # (see print.rb) + # This is the 'print' component of the REPL. # @return [Proc] The Proc to use for printing by default by all # Pry instances. attr_accessor :print - # Set/Get the Hash that defines Pry hooks used by default by all Pry + # Get/Set the Hash that defines Pry hooks used by default by all Pry # instances. - # (see print.rb) # @return [Hash] The hooks used by default by all Pry instances. # @example # Pry.hooks :before_session => proc { puts "hello" }, # :after_session => proc { puts "goodbye" } attr_accessor :hooks - # Set/Get the array of Procs to be used for the prompts by default by + # Get/Set the array of Procs to be used for the prompts by default by # all Pry instances. - # (see prompts.rb) # @return [Array] The array of Procs to be used for the # prompts by default by all Pry instances. attr_accessor :default_prompt @@ -65,7 +59,8 @@ class Pry # Start a Pry REPL. # @param [Object, Binding] target The receiver of the Pry session - # @param options (see Pry#initialize) + # @param [Hash] options + # @option options (see Pry#initialize) # @example # Pry.start(Object.new, :input => MyInput.new) def self.start(target=TOPLEVEL_BINDING, options={}) diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb index 1c411642..eb7be03b 100644 --- a/lib/pry/pry_instance.rb +++ b/lib/pry/pry_instance.rb @@ -14,11 +14,14 @@ class Pry # commands. (see commands.rb) # @option options [Hash] :hooks The defined hook Procs (see hooks.rb) # @option options [Array] :default_prompt The array of Procs - # to use for the prompts. - # @option options [Proc] :print The Proc to use for the 'print' componenent of the REPL + # to use for the prompts. (see prompts.rb) + # @option options [Proc] :print The Proc to use for the 'print' + # component of the REPL. (see print.rb) def initialize(options={}) - default_options = ConfigOptions.each_with_object({}) { |v, h| h[v] = Pry.send(v) } + h = {} + ConfigOptions.each { |v| h[v] = Pry.send(v) } + default_options = h default_options.merge!(options) ConfigOptions.each do |key| @@ -68,7 +71,7 @@ class Pry target.eval("_ = Pry.last_result") break_level = catch(:breakout) do - nesting << [nesting.size, target_self] + nesting.push [nesting.size, target_self] loop do rep(target) end @@ -128,8 +131,8 @@ class Pry eval_string = "" loop do val = input.read(prompt(eval_string, target)) - eval_string << "#{val.chomp}\n" process_commands(val, eval_string, target) + eval_string << "#{val.chomp}\n" break eval_string if valid_expression?(eval_string) end @@ -139,7 +142,7 @@ class Pry # prior to Ruby expressions. # Commands can be modified/configured by the user: see `Pry::Commands` # This method should not need to be invoked directly - it is called - # by `Pry#r` + # by `Pry#r`. # @param [String] val The current line of input. # @param [String] eval_string The cumulative lines of input for # multi-line input. @@ -150,8 +153,10 @@ class Pry pattern, action = commands.commands.find { |k, v| Array(k).any? { |a| a === val } } if pattern + last_match = Regexp.last_match + options = { - :captures => $~ ? $~.captures : nil, + :captures => last_match ? last_match.captures : nil, :eval_string => eval_string, :target => target, :val => val, @@ -211,7 +216,6 @@ class Pry true end end - # Return a `Binding` object for `target` or return `target` if it is # already a `Binding`.