Module: IRB::Debug

Defined in:
lib/irb/debug.rb,
lib/irb/debug/ui.rb
more...

Defined Under Namespace

Modules: SkipPathHelperForIRB Classes: UI

Constant Summary collapse

IRB_DIR =
File.expand_path('..', __dir__)

Class Method Summary collapse

Class Method Details

.insert_debug_break(pre_cmds: nil, do_cmds: nil) ⇒ Object

[View source]

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/irb/debug.rb', line 8

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

.setup(irb) ⇒ Object

[View source]

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/irb/debug.rb', line 25

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 == "<internal:prelude>"
      end
      frames
    end

    DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
  end

  if !DEBUGGER__::CONFIG[:no_hint] && irb.context.io.is_a?(RelineInputMethod)
    Reline.output_modifier_proc = proc do |input, complete:|
      unless input.strip.empty?
        cmd = input.split(/\s/, 2).first

        if !complete && DEBUGGER__.commands.key?(cmd)
          input = input.sub(/\n$/, " # debug command\n")
        end
      end

      irb.context.colorize_input(input, complete: complete)
    end
  end

  true
end