diff --git a/lib/pry.rb b/lib/pry.rb index efc2c032..b0d92260 100644 --- a/lib/pry.rb +++ b/lib/pry.rb @@ -4,6 +4,7 @@ direc = File.dirname(__FILE__) $LOAD_PATH << File.expand_path(direc) +$LOAD_PATH << "." require "method_source" require 'shellwords' diff --git a/lib/pry/commands.rb b/lib/pry/commands.rb index f70937ee..3d0d6256 100644 --- a/lib/pry/commands.rb +++ b/lib/pry/commands.rb @@ -35,6 +35,20 @@ class Pry text.split.drop(1).join(' ') end + get_method_object = lambda do |meth_name, target, options| + if options[:M] + target.eval("instance_method(:#{meth_name})") + elsif options[:m] + target.eval("method(:#{meth_name})") + else + begin + target.eval("method(:#{meth_name})") + rescue + target.eval("instance_method(:#{meth_name})") + end + end + end + command "!", "Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop." do output.puts "Input buffer cleared!" opts[:eval_string].clear @@ -386,11 +400,22 @@ e.g: eval-file -c self "hello.rb" if obj == "/" throw(:breakout, 1) if opts[:nesting].level > 0 next - end + end target.eval("#{obj}.pry") end + process_comment_markup = lambda do |comment, code_type| + comment.gsub(/(?:\s*\n)?(.*?)\s*<\/code>/m) { Pry.color ? CodeRay.scan($1, code_type).term : $1 }. + gsub(/(?:\s*\n)?(.*?)\s*<\/em>/m) { Pry.color ? "\e[32m#{$1}\e[0m": $1 }. + gsub(/(?:\s*\n)?(.*?)\s*<\/i>/m) { Pry.color ? "\e[34m#{$1}\e[0m" : $1 }. + gsub(/\B\+(.*)\+\B/) { Pry.color ? "\e[32m#{$1}\e[0m": $1 } + end + + strip_leading_hash_from_ruby_comments = lambda do |comment| + comment.gsub /^\s*#\s*/, '' + end + command "show-doc", "Show the comments above METH. Type `show-doc --help` for more info." do |*args| options = {} target = target() @@ -430,41 +455,46 @@ e.g show-doc hello_method end begin - if options[:M] - meth = target.eval("instance_method(:#{meth_name})") - elsif options[:m] - meth = target.eval("method(:#{meth_name})") - else - begin - meth = target.eval("method(:#{meth_name})") - rescue - meth = target.eval("instance_method(:#{meth_name})") - end - end + meth = get_method_object.call(meth_name, target, options) rescue output.puts "Invalid method name: #{meth_name}. Type `show-doc --help` for help" next end + code_type = :ruby + if Pry.has_pry_doc info = Pry::MethodInfo.info_for(meth) if !info doc = meth.comment else doc = info.docstring + code_type = info.source_type end else - doc = meth.comment + doc = strip_leading_hash_from_ruby_comments.call(meth.comment) end + + doc = process_comment_markup.call(doc, code_type) + file, line = meth.source_location check_for_dynamically_defined_method.call(file) - output.puts "--\nFrom #{file} @ line ~#{line}:\n--" - + doc = case code_type + when :ruby + "--\nFrom #{file} @ line ~#{line}:\n--" + else + "--\nFrom Ruby Core (C Method):\n-" + end + output.puts doc doc end + strip_comments_from_c_code = lambda do |code| + code.sub /\A\s*\/\*.*?\*\/\s*/m, '' + end + command "show-method", "Show the source for METH. Type `show-method --help` for more info." do |*args| options = {} target = target() @@ -480,7 +510,7 @@ e.g: show-method hello_method options[:M] = true end - opts.on("-m", "--methods", "Operate on methods..") do + opts.on("-m", "--methods", "Operate on methods.") do options[:m] = true end @@ -500,32 +530,19 @@ e.g: show-method hello_method # If no method name is given then use current method, if it exists meth_name = meth_name_from_binding.call(target) if !meth_name - if !meth_name output.puts "You need to specify a method. Type `show-method --help` for help" next end begin - if options[:M] - meth = target.eval("instance_method(:#{meth_name})") - elsif options[:m] - meth = target.eval("method(:#{meth_name})") - else - begin - meth = target.eval("method(:#{meth_name})") - rescue - meth = target.eval("instance_method(:#{meth_name})") - end - end - + meth = get_method_object.call(meth_name, target, options) rescue - target_self = target.eval('self') output.puts "Invalid method name: #{meth_name}. Type `show-method --help` for help" next end - meth_type = :ruby + code_type = :ruby # Try to find source for C methods using MethodInfo (if possible) if Pry.has_pry_doc && meth.source_location.nil? @@ -536,7 +553,8 @@ e.g: show-method hello_method next end code = info.source - meth_type = :c + code = strip_comments_from_c_code.call(code) + code_type = :c else code = meth.source end @@ -544,10 +562,15 @@ e.g: show-method hello_method file, line = meth.source_location check_for_dynamically_defined_method.call(file) - output.puts "--\nFrom #{file} @ line #{line}:\n--" + code = case code_type + when :ruby + "--\nFrom #{file} @ line #{line}:\n--" + else + "--\nFrom Ruby Core (C Method):\n--" + end if Pry.color - code = CodeRay.scan(code, meth_type).term + code = CodeRay.scan(code, code_type).term end output.puts code diff --git a/lib/pry/pry_class.rb b/lib/pry/pry_class.rb index 848c0b86..5a9a541d 100644 --- a/lib/pry/pry_class.rb +++ b/lib/pry/pry_class.rb @@ -17,6 +17,11 @@ class Pry # @return [Object] The last result. attr_accessor :last_result + # Get last exception raised. + # This method should not need to be accessed directly. + # @return [Exception] The last exception. + attr_accessor :last_exception + # Get the active Pry instance that manages the active Pry session. # This method should not need to be accessed directly. # @return [Pry] The active Pry instance. diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb index acefb570..e9e8183a 100644 --- a/lib/pry/pry_instance.rb +++ b/lib/pry/pry_instance.rb @@ -135,21 +135,20 @@ class Pry Readline.completion_proc = Pry::InputCompleter.build_completion_proc(target, commands.commands.keys) end - # eval the expression and save to last_result - # Do not want __FILE__, __LINE__ here because we need to distinguish - # (eval) methods for show-method and friends. - Pry.last_result = target.eval r(target) # save the pry instance to active_instance Pry.active_instance = self - - # define locals _pry_ and _ (active instance and last expression) target.eval("_pry_ = Pry.active_instance") - target.eval("_ = Pry.last_result") + + # eval the expression and save to last_result + # Do not want __FILE__, __LINE__ here because we need to distinguish + # (eval) methods for show-method and friends. + # This also sets the `_` local for the session. + set_last_result(target.eval(r(target)), target) rescue SystemExit => e exit rescue Exception => e - e + set_last_exception(e, target) end # Perform a read. @@ -190,6 +189,22 @@ class Pry end end + # Set the last result of an eval. + # @param [Object] result The result. + # @param [Binding] target The binding to set `_` on. + def set_last_result(result, target) + Pry.last_result = result + target.eval("_ = Pry.last_result") + end + + # Set the last exception for a session. + # @param [Exception] ex The exception. + # @param [Binding] target The binding to set `_ex_` on. + def set_last_exception(ex, target) + Pry.last_exception = ex + target.eval("_ex_ = Pry.last_exception") + end + # Process Pry commands. Pry commands are not Ruby methods and are evaluated # prior to Ruby expressions. # Commands can be modified/configured by the user: see `Pry::Commands` diff --git a/lib/pry/version.rb b/lib/pry/version.rb index b8a1afee..edbaa020 100644 --- a/lib/pry/version.rb +++ b/lib/pry/version.rb @@ -1,3 +1,3 @@ class Pry - VERSION = "0.7.0pre2" + VERSION = "0.7.0pre3" end