Skip to content

Commit 30faa13

Browse files
authored
Add debug command (#446)
1 parent 3348c46 commit 30faa13

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

lib/irb.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,8 @@ def IRB.irb_abort(irb, exception = Abort)
393393
end
394394

395395
class Irb
396+
DIR_NAME = __dir__
397+
396398
ASSIGNMENT_NODE_TYPES = [
397399
# Local, instance, global, class, constant, instance, and index assignment:
398400
# "foo = bar",
@@ -434,6 +436,16 @@ def initialize(workspace = nil, input_method = nil)
434436
@scanner = RubyLex.new
435437
end
436438

439+
def debug_break
440+
# it means the debug command is executed
441+
if defined?(DEBUGGER__) && DEBUGGER__.respond_to?(:original_capture_frames)
442+
# after leaving this initial breakpoint, revert the capture_frames patch
443+
DEBUGGER__.singleton_class.send(:alias_method, :capture_frames, :original_capture_frames)
444+
# and remove the redundant method
445+
DEBUGGER__.singleton_class.send(:undef_method, :original_capture_frames)
446+
end
447+
end
448+
437449
def run(conf = IRB.conf)
438450
conf[:IRB_RC].call(context) if conf[:IRB_RC]
439451
conf[:MAIN_CONTEXT] = context
@@ -931,5 +943,6 @@ def irb(show_code: true)
931943
binding_irb = IRB::Irb.new(workspace)
932944
binding_irb.context.irb_path = File.expand_path(source_location[0])
933945
binding_irb.run(IRB.conf)
946+
binding_irb.debug_break
934947
end
935948
end

lib/irb/cmd/debug.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
require_relative "nop"
2+
3+
module IRB
4+
# :stopdoc:
5+
6+
module ExtendCommand
7+
class Debug < Nop
8+
def execute(*args)
9+
require "debug/session"
10+
DEBUGGER__.start(nonstop: true)
11+
DEBUGGER__.singleton_class.send(:alias_method, :original_capture_frames, :capture_frames)
12+
13+
def DEBUGGER__.capture_frames(skip_path_prefix)
14+
frames = original_capture_frames(skip_path_prefix)
15+
frames.reject! do |frame|
16+
frame.realpath&.start_with?(::IRB::Irb::DIR_NAME) || frame.path.match?(/internal:prelude/)
17+
end
18+
frames
19+
end
20+
21+
file, lineno = IRB::Irb.instance_method(:debug_break).source_location
22+
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, oneshot: true, hook_call: false)
23+
# exit current Irb#run call
24+
throw :IRB_EXIT
25+
rescue LoadError => e
26+
puts <<~MSG
27+
You need to install the debug gem before using this command.
28+
If you use `bundle exec`, please add `gem "debug"` into your Gemfile.
29+
MSG
30+
end
31+
end
32+
end
33+
end

lib/irb/extend-command.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ def irb_context
116116
[:kill, OVERRIDE_PRIVATE_ONLY],
117117
],
118118

119+
[
120+
:irb_debug, :Debug, "cmd/debug",
121+
[:debug, NO_OVERRIDE],
122+
],
119123
[
120124
:irb_help, :Help, "cmd/help",
121125
[:help, NO_OVERRIDE],

0 commit comments

Comments
 (0)