Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add commands to start and use the debugger #449

Merged
merged 9 commits into from
Nov 21, 2022
2 changes: 1 addition & 1 deletion lib/irb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ def initialize(workspace = nil, input_method = nil)
@context = Context.new(self, workspace, input_method)
@context.main.extend ExtendCommandBundle
@context.command_aliases.each do |alias_name, cmd_name|
next if @context.symbol_alias(alias_name)
next if @context.symbol_alias?(alias_name) || @context.main.respond_to?(alias_name)
@context.main.install_alias_method(alias_name, cmd_name)
end
@signal_status = :IN_IRB
Expand Down
17 changes: 17 additions & 0 deletions lib/irb/cmd/break.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require_relative "debug"

module IRB
# :stopdoc:

module ExtendCommand
class Break < Debug
def execute(*args)
super(['break', *args].join(' '))
end
end
end

# :startdoc:
end
17 changes: 17 additions & 0 deletions lib/irb/cmd/continue.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require_relative "debug"

module IRB
# :stopdoc:

module ExtendCommand
class Continue < Debug
def execute(*args)
super(['continue', *args].join(' '))
end
end
end

# :startdoc:
end
9 changes: 7 additions & 2 deletions lib/irb/cmd/debug.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Debug < Nop
].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
IRB_DIR = File.expand_path('..', __dir__)

def execute(*args)
def execute(debug_command = nil)
unless binding_irb?
puts "`debug` command is only available when IRB is started with binding.irb"
return
Expand All @@ -25,11 +25,16 @@ def execute(*args)
return
end

command = nil
if debug_command
command = ['irb', nil, debug_command]
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, oneshot: true, hook_call: false)
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, oneshot: true, hook_call: false, command: command)
k0kubun marked this conversation as resolved.
Show resolved Hide resolved
# exit current Irb#run call
throw :IRB_EXIT
end
Expand Down
17 changes: 17 additions & 0 deletions lib/irb/cmd/finish.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require_relative "debug"

module IRB
# :stopdoc:

module ExtendCommand
class Finish < Debug
def execute(*args)
super(['finish', *args].join(' '))
end
end
end

# :startdoc:
end
17 changes: 17 additions & 0 deletions lib/irb/cmd/next.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require_relative "debug"

module IRB
# :stopdoc:

module ExtendCommand
class Next < Debug
def execute(*args)
super(['next', *args].join(' '))
end
end
end

# :startdoc:
end
8 changes: 4 additions & 4 deletions lib/irb/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,9 @@ def evaluate(line, line_no, exception: nil) # :nodoc:
@workspace.local_variable_set(:_, exception)
end

# Transform a non-identifier alias (ex: @, $)
# Transform a non-identifier alias (@, $) or keywords (next, break)
command, args = line.split(/\s/, 2)
if original = symbol_alias(command)
if original = command_aliases[command.to_sym]
line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
command = original
end
Expand Down Expand Up @@ -546,9 +546,9 @@ def local_variables # :nodoc:
end

# Return a command name if it's aliased from the argument and it's not an identifier.
def symbol_alias(command)
def symbol_alias?(command)
return nil if command.match?(/\A\w+\z/)
command_aliases[command.to_sym]
command_aliases.key?(command.to_sym)
end
end
end
15 changes: 15 additions & 0 deletions lib/irb/extend-command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@ def irb_context
:irb_debug, :Debug, "cmd/debug",
[:debug, NO_OVERRIDE],
],
[
:irb_break, :Break, "cmd/break",
],
[
:irb_next, :Next, "cmd/next",
],
[
:irb_continue, :Continue, "cmd/continue",
[:continue, NO_OVERRIDE],
],
[
:irb_finish, :Finish, "cmd/finish",
[:finish, NO_OVERRIDE],
],

[
:irb_help, :Help, "cmd/help",
[:help, NO_OVERRIDE],
Expand Down
4 changes: 4 additions & 0 deletions lib/irb/init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,12 @@ def IRB.init_config(ap_path)
@CONF[:AT_EXIT] = []

@CONF[:COMMAND_ALIASES] = {
# Symbol aliases
:'$' => :show_source,
:'@' => :whereami,
# Keyword aliases
:break => :irb_break,
:next => :irb_next,
}
end

Expand Down
2 changes: 1 addition & 1 deletion lib/irb/ruby-lex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def set_input(io, p = nil, context:, &block)
else
# Accept any single-line input starting with a non-identifier alias (ex: @, $)
command = code.split(/\s/, 2).first
if context.symbol_alias(command)
if context.symbol_alias?(command)
next true
end

Expand Down