Skip to content

Commit 976100c

Browse files
authored
Add commands to start and use the debugger (#449)
* Seamlessly integrate a few debug commands * Improve the break command support * Utilize skip_src option if available * Add step and delete commands * Write end-to-end tests for each debugger command * Add documentation * Add backtrace, info, catch commands
1 parent ae7de1e commit 976100c

File tree

19 files changed

+487
-37
lines changed

19 files changed

+487
-37
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ group :development do
1111
gem "stackprof" if is_unix && !is_truffleruby
1212
gem "test-unit"
1313
gem "reline", github: "ruby/reline" if ENV["WITH_LATEST_RELINE"] == "true"
14+
gem "debug"
1415
end

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ The following commands are available on IRB.
9090
* Show the source code around binding.irb again.
9191
* `debug`
9292
* Start the debugger of debug.gem.
93+
* `break`, `delete`, `next`, `step`, `continue`, `finish`, `backtrace`, `info`, `catch`
94+
* Start the debugger of debug.gem and run the command on it.
9395

9496
## Documentation
9597

lib/irb.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@
9696
# * Show the source code around binding.irb again.
9797
# * debug
9898
# * Start the debugger of debug.gem.
99+
# * break, delete, next, step, continue, finish, backtrace, info, catch
100+
# * Start the debugger of debug.gem and run the command on it.
99101
#
100102
# == Configuration
101103
#
@@ -470,10 +472,6 @@ class Irb
470472
def initialize(workspace = nil, input_method = nil)
471473
@context = Context.new(self, workspace, input_method)
472474
@context.main.extend ExtendCommandBundle
473-
@context.command_aliases.each do |alias_name, cmd_name|
474-
next if @context.symbol_alias(alias_name)
475-
@context.main.install_alias_method(alias_name, cmd_name)
476-
end
477475
@signal_status = :IN_IRB
478476
@scanner = RubyLex.new
479477
end

lib/irb/cmd/backtrace.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "debug"
4+
5+
module IRB
6+
# :stopdoc:
7+
8+
module ExtendCommand
9+
class Backtrace < Debug
10+
def self.transform_args(args)
11+
args&.dump
12+
end
13+
14+
def execute(*args)
15+
super(pre_cmds: ["backtrace", *args].join(" "))
16+
end
17+
end
18+
end
19+
20+
# :startdoc:
21+
end

lib/irb/cmd/break.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "debug"
4+
5+
module IRB
6+
# :stopdoc:
7+
8+
module ExtendCommand
9+
class Break < Debug
10+
def self.transform_args(args)
11+
args&.dump
12+
end
13+
14+
def execute(args = nil)
15+
super(pre_cmds: "break #{args}")
16+
end
17+
end
18+
end
19+
20+
# :startdoc:
21+
end

lib/irb/cmd/catch.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "debug"
4+
5+
module IRB
6+
# :stopdoc:
7+
8+
module ExtendCommand
9+
class Catch < Debug
10+
def self.transform_args(args)
11+
args&.dump
12+
end
13+
14+
def execute(*args)
15+
super(pre_cmds: ["catch", *args].join(" "))
16+
end
17+
end
18+
end
19+
20+
# :startdoc:
21+
end

lib/irb/cmd/continue.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "debug"
4+
5+
module IRB
6+
# :stopdoc:
7+
8+
module ExtendCommand
9+
class Continue < Debug
10+
def execute(*args)
11+
super(do_cmds: ["continue", *args].join(" "))
12+
end
13+
end
14+
end
15+
16+
# :startdoc:
17+
end

lib/irb/cmd/debug.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Debug < Nop
1111
].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
1212
IRB_DIR = File.expand_path('..', __dir__)
1313

14-
def execute(*args)
14+
def execute(pre_cmds: nil, do_cmds: nil)
1515
unless binding_irb?
1616
puts "`debug` command is only available when IRB is started with binding.irb"
1717
return
@@ -25,11 +25,19 @@ def execute(*args)
2525
return
2626
end
2727

28+
options = { oneshot: true, hook_call: false }
29+
if pre_cmds || do_cmds
30+
options[:command] = ['irb', pre_cmds, do_cmds]
31+
end
32+
if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
33+
options[:skip_src] = true
34+
end
35+
2836
# To make debugger commands like `next` or `continue` work without asking
2937
# the user to quit IRB after that, we need to exit IRB first and then hit
3038
# a TracePoint on #debug_break.
3139
file, lineno = IRB::Irb.instance_method(:debug_break).source_location
32-
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, oneshot: true, hook_call: false)
40+
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
3341
# exit current Irb#run call
3442
throw :IRB_EXIT
3543
end

lib/irb/cmd/delete.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "debug"
4+
5+
module IRB
6+
# :stopdoc:
7+
8+
module ExtendCommand
9+
class Delete < Debug
10+
def execute(*args)
11+
super(pre_cmds: ["delete", *args].join(" "))
12+
end
13+
end
14+
end
15+
16+
# :startdoc:
17+
end

lib/irb/cmd/finish.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "debug"
4+
5+
module IRB
6+
# :stopdoc:
7+
8+
module ExtendCommand
9+
class Finish < Debug
10+
def execute(*args)
11+
super(do_cmds: ["finish", *args].join(" "))
12+
end
13+
end
14+
end
15+
16+
# :startdoc:
17+
end

0 commit comments

Comments
 (0)