diff options
author | Stan Lo <stan001212@gmail.com> | 2022-11-18 09:11:19 +0000 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2022-11-18 09:11:23 +0000 |
commit | 00872d120b017de2270fe18068cea2d37d41ed71 (patch) | |
tree | c346ab6256c7ed0c0aac9814daea88e16fdd9d26 /lib | |
parent | a80b66e7ebf1179964b416cee6fd236048a73dcf (diff) | |
download | ruby-00872d120b017de2270fe18068cea2d37d41ed71.tar.gz |
[ruby/irb] Add debug command (https://github.com/ruby/irb/pull/446)
https://github.com/ruby/irb/commit/30faa13fa3
Diffstat (limited to 'lib')
-rw-r--r-- | lib/irb.rb | 13 | ||||
-rw-r--r-- | lib/irb/cmd/debug.rb | 33 | ||||
-rw-r--r-- | lib/irb/extend-command.rb | 4 |
3 files changed, 50 insertions, 0 deletions
diff --git a/lib/irb.rb b/lib/irb.rb index 1c38960cc0..1cd89d295c 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -393,6 +393,8 @@ module IRB end class Irb + DIR_NAME = __dir__ + ASSIGNMENT_NODE_TYPES = [ # Local, instance, global, class, constant, instance, and index assignment: # "foo = bar", @@ -434,6 +436,16 @@ module IRB @scanner = RubyLex.new end + def debug_break + # it means the debug command is executed + if defined?(DEBUGGER__) && DEBUGGER__.respond_to?(:original_capture_frames) + # after leaving this initial breakpoint, revert the capture_frames patch + DEBUGGER__.singleton_class.send(:alias_method, :capture_frames, :original_capture_frames) + # and remove the redundant method + DEBUGGER__.singleton_class.send(:undef_method, :original_capture_frames) + end + end + def run(conf = IRB.conf) conf[:IRB_RC].call(context) if conf[:IRB_RC] conf[:MAIN_CONTEXT] = context @@ -931,5 +943,6 @@ class Binding binding_irb = IRB::Irb.new(workspace) binding_irb.context.irb_path = File.expand_path(source_location[0]) binding_irb.run(IRB.conf) + binding_irb.debug_break end end diff --git a/lib/irb/cmd/debug.rb b/lib/irb/cmd/debug.rb new file mode 100644 index 0000000000..8aab40cf84 --- /dev/null +++ b/lib/irb/cmd/debug.rb @@ -0,0 +1,33 @@ +require_relative "nop" + +module IRB + # :stopdoc: + + module ExtendCommand + class Debug < Nop + def execute(*args) + require "debug/session" + DEBUGGER__.start(nonstop: true) + DEBUGGER__.singleton_class.send(:alias_method, :original_capture_frames, :capture_frames) + + def DEBUGGER__.capture_frames(skip_path_prefix) + frames = original_capture_frames(skip_path_prefix) + frames.reject! do |frame| + frame.realpath&.start_with?(::IRB::Irb::DIR_NAME) || frame.path.match?(/internal:prelude/) + end + frames + end + + file, lineno = IRB::Irb.instance_method(:debug_break).source_location + DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, oneshot: true, hook_call: false) + # exit current Irb#run call + throw :IRB_EXIT + rescue LoadError => e + puts <<~MSG + You need to install the debug gem before using this command. + If you use `bundle exec`, please add `gem "debug"` into your Gemfile. + MSG + end + end + end +end diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb index acc23c9920..7da75fe147 100644 --- a/lib/irb/extend-command.rb +++ b/lib/irb/extend-command.rb @@ -117,6 +117,10 @@ module IRB # :nodoc: ], [ + :irb_debug, :Debug, "cmd/debug", + [:debug, NO_OVERRIDE], + ], + [ :irb_help, :Help, "cmd/help", [:help, NO_OVERRIDE], ], |