[ruby/irb] Support repeating debugger input by passing empty input

to it
(https://github.com/ruby/irb/pull/856)

* Test IRB's behaviour with empty input

* Handle empty input and pass it to debugger

Since `rdbg` accepts empty input to repeat the previous command, IRB
should take empty input in `irb:rdbg` sessions and pass them to the
debugger.

Currently, IRB simply ignores empty input and does nothing. This commit
creates `EmptyInput` to represent empty input so it can fit into the
current IRB's input processing flow in `Irb#eval_input`.

https://github.com/ruby/irb/commit/0e9db419be
This commit is contained in:
Stan Lo 2024-02-16 16:12:50 +00:00 committed by git
parent ff4f5c0cdd
commit b315826377
4 changed files with 71 additions and 5 deletions

View File

@ -1082,16 +1082,17 @@ module IRB
loop do
code = readmultiline
break unless code
if code != "\n"
yield build_statement(code), @line_no
end
yield build_statement(code), @line_no
@line_no += code.count("\n")
rescue RubyLex::TerminateLineInput
end
end
def build_statement(code)
if code.match?(/\A\n*\z/)
return Statement::EmptyInput.new
end
code.force_encoding(@context.io.encoding)
command_or_alias, arg = code.split(/\s/, 2)
# Transform a non-identifier alias (@, $) or keywords (next, break)

View File

@ -20,6 +20,29 @@ module IRB
raise NotImplementedError
end
class EmptyInput < Statement
def is_assignment?
false
end
def suppresses_echo?
true
end
# Debugger takes empty input to repeat the last command
def should_be_handled_by_debugger?
true
end
def code
""
end
def evaluable_code
code
end
end
class Expression < Statement
def initialize(code, is_assignment)
@code = code

View File

@ -6,7 +6,7 @@ require "tmpdir"
require_relative "helper"
module TestIRB
class DebugCommandTest < IntegrationTestCase
class DebuggerIntegrationTest < IntegrationTestCase
def setup
super
@ -434,5 +434,29 @@ module TestIRB
assert_match(/irb\(main\):001> next/, output)
assert_include(output, "Multi-IRB commands are not available when the debugger is enabled.")
end
def test_irb_passes_empty_input_to_debugger_to_repeat_the_last_command
write_ruby <<~'ruby'
binding.irb
puts "foo"
puts "bar"
puts "baz"
ruby
output = run_ruby_file do
type "next"
type ""
# Test that empty input doesn't repeat expressions
type "123"
type ""
type "next"
type ""
type ""
end
assert_include(output, "=> 2\| puts \"foo\"")
assert_include(output, "=> 3\| puts \"bar\"")
assert_include(output, "=> 4\| puts \"baz\"")
end
end
end

View File

@ -58,6 +58,24 @@ module TestIRB
assert_include output, "=> \"It's a foo\""
assert_include output, "=> \"It's a bar\""
end
def test_empty_input_echoing_behaviour
write_ruby <<~'RUBY'
binding.irb
RUBY
output = run_ruby_file do
type ""
type " "
type "exit"
end
# Input cramped together due to how Reline's Reline::GeneralIO works
assert_include(
output,
"irb(main):001> irb(main):002> irb(main):002> irb(main):002> => nil\r\n"
)
end
end
class IrbIOConfigurationTest < TestCase