# frozen_string_literal: true
module IRB
module Debug
IRB_DIR = File.expand_path('..', __dir__)
class << self
def insert_debug_break(pre_cmds: nil, do_cmds: nil)
options = { oneshot: true, hook_call: false }
if pre_cmds || do_cmds
options[:command] = ['irb', pre_cmds, do_cmds]
end
if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
options[:skip_src] = true
end
# To make debugger commands like `next` or `continue` work without asking
# the user to quit IRB after that, we need to exit IRB first and then hit
# a TracePoint on #debug_break.
file, lineno = IRB::Irb.instance_method(:debug_break).source_location
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
end
def setup(irb)
# When debug session is not started at all
unless defined?(DEBUGGER__::SESSION)
begin
require "debug/session"
rescue LoadError # debug.gem is not written in Gemfile
return false unless load_bundled_debug_gem
end
DEBUGGER__::CONFIG.set_config
configure_irb_for_debugger(irb)
DEBUGGER__.initialize_session{ IRB::Debug::UI.new(irb) }
end
# When debug session was previously started but not by IRB
if defined?(DEBUGGER__::SESSION) && !irb.context.with_debugger
configure_irb_for_debugger(irb)
DEBUGGER__::SESSION.reset_ui(IRB::Debug::UI.new(irb))
end
# Apply patches to debug gem so it skips IRB frames
unless DEBUGGER__.respond_to?(:capture_frames_without_irb)
DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames)
def DEBUGGER__.capture_frames(*args)
frames = capture_frames_without_irb(*args)
frames.reject! do |frame|
frame.realpath&.start_with?(IRB_DIR) || frame.path&.start_with?("