[ruby/irb] Polish the exit! command and its tests
(https://github.com/ruby/irb/pull/867) * Remove IRB.irb_exit! method It's not necessary to introduce a new method just for the exit! command at this moment. * Rename ExitForcedAction to ForceExit * Move force exit tests to a dedicated file * Fix nested history saving with exit! command Because we switched to use `Kernel#exit` instead of `exit!`, the outer session's ensure block in `Irb#run` will be run, which will save the history. This means the separate check to save history when force exiting is no longer necessary. * execute_lines helper should also capture IRB setup's output This prevents setup warnings from being printed to test output while allowing those output to be tested. * Update readme https://github.com/ruby/irb/commit/899d10ade1
This commit is contained in:
parent
429eeb09f2
commit
5c4657f883
13
lib/irb.rb
13
lib/irb.rb
@ -889,10 +889,6 @@ module IRB
|
|||||||
throw :IRB_EXIT, false
|
throw :IRB_EXIT, false
|
||||||
end
|
end
|
||||||
|
|
||||||
def IRB.irb_exit!(*)
|
|
||||||
throw :IRB_EXIT, true
|
|
||||||
end
|
|
||||||
|
|
||||||
# Aborts then interrupts irb.
|
# Aborts then interrupts irb.
|
||||||
#
|
#
|
||||||
# Will raise an Abort exception, or the given +exception+.
|
# Will raise an Abort exception, or the given +exception+.
|
||||||
@ -972,8 +968,7 @@ module IRB
|
|||||||
conf[:IRB_RC].call(context) if conf[:IRB_RC]
|
conf[:IRB_RC].call(context) if conf[:IRB_RC]
|
||||||
conf[:MAIN_CONTEXT] = context
|
conf[:MAIN_CONTEXT] = context
|
||||||
|
|
||||||
supports_history_saving = conf[:SAVE_HISTORY] && context.io.support_history_saving?
|
save_history = !in_nested_session && conf[:SAVE_HISTORY] && context.io.support_history_saving?
|
||||||
save_history = !in_nested_session && supports_history_saving
|
|
||||||
|
|
||||||
if save_history
|
if save_history
|
||||||
context.io.load_history
|
context.io.load_history
|
||||||
@ -993,12 +988,8 @@ module IRB
|
|||||||
trap("SIGINT", prev_trap)
|
trap("SIGINT", prev_trap)
|
||||||
conf[:AT_EXIT].each{|hook| hook.call}
|
conf[:AT_EXIT].each{|hook| hook.call}
|
||||||
|
|
||||||
if forced_exit
|
|
||||||
context.io.save_history if supports_history_saving
|
|
||||||
Kernel.exit(0)
|
|
||||||
else
|
|
||||||
context.io.save_history if save_history
|
context.io.save_history if save_history
|
||||||
end
|
Kernel.exit(0) if forced_exit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,12 +6,12 @@ module IRB
|
|||||||
# :stopdoc:
|
# :stopdoc:
|
||||||
|
|
||||||
module ExtendCommand
|
module ExtendCommand
|
||||||
class ExitForcedAction < Nop
|
class ForceExit < Nop
|
||||||
category "IRB"
|
category "IRB"
|
||||||
description "Exit the current process."
|
description "Exit the current process."
|
||||||
|
|
||||||
def execute(*)
|
def execute(*)
|
||||||
IRB.irb_exit!
|
throw :IRB_EXIT, true
|
||||||
rescue UncaughtThrowError
|
rescue UncaughtThrowError
|
||||||
Kernel.exit(0)
|
Kernel.exit(0)
|
||||||
end
|
end
|
@ -37,7 +37,7 @@ module IRB # :nodoc:
|
|||||||
[:irb_quit, OVERRIDE_PRIVATE_ONLY],
|
[:irb_quit, OVERRIDE_PRIVATE_ONLY],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
:irb_exit!, :ExitForcedAction, "cmd/exit_forced_action",
|
:irb_exit!, :ForceExit, "cmd/force_exit",
|
||||||
[:exit!, OVERRIDE_PRIVATE_ONLY],
|
[:exit!, OVERRIDE_PRIVATE_ONLY],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
51
test/irb/cmd/test_force_exit.rb
Normal file
51
test/irb/cmd/test_force_exit.rb
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# frozen_string_literal: false
|
||||||
|
require 'irb'
|
||||||
|
|
||||||
|
require_relative "../helper"
|
||||||
|
|
||||||
|
module TestIRB
|
||||||
|
class ForceExitTest < IntegrationTestCase
|
||||||
|
def test_forced_exit_finishes_process_immediately
|
||||||
|
write_ruby <<~'ruby'
|
||||||
|
puts "First line"
|
||||||
|
puts "Second line"
|
||||||
|
binding.irb
|
||||||
|
puts "Third line"
|
||||||
|
binding.irb
|
||||||
|
puts "Fourth line"
|
||||||
|
ruby
|
||||||
|
|
||||||
|
output = run_ruby_file do
|
||||||
|
type "123"
|
||||||
|
type "456"
|
||||||
|
type "exit!"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_match(/First line\r\n/, output)
|
||||||
|
assert_match(/Second line\r\n/, output)
|
||||||
|
assert_match(/irb\(main\):001> 123/, output)
|
||||||
|
assert_match(/irb\(main\):002> 456/, output)
|
||||||
|
refute_match(/Third line\r\n/, output)
|
||||||
|
refute_match(/Fourth line\r\n/, output)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_forced_exit_in_nested_sessions
|
||||||
|
write_ruby <<~'ruby'
|
||||||
|
def foo
|
||||||
|
binding.irb
|
||||||
|
end
|
||||||
|
|
||||||
|
binding.irb
|
||||||
|
binding.irb
|
||||||
|
ruby
|
||||||
|
|
||||||
|
output = run_ruby_file do
|
||||||
|
type "123"
|
||||||
|
type "foo"
|
||||||
|
type "exit!"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_match(/irb\(main\):001> 123/, output)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -34,6 +34,7 @@ module TestIRB
|
|||||||
end
|
end
|
||||||
|
|
||||||
def execute_lines(*lines, conf: {}, main: self, irb_path: nil)
|
def execute_lines(*lines, conf: {}, main: self, irb_path: nil)
|
||||||
|
capture_output do
|
||||||
IRB.init_config(nil)
|
IRB.init_config(nil)
|
||||||
IRB.conf[:VERBOSE] = false
|
IRB.conf[:VERBOSE] = false
|
||||||
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
||||||
@ -44,7 +45,6 @@ module TestIRB
|
|||||||
irb.context.return_format = "=> %s\n"
|
irb.context.return_format = "=> %s\n"
|
||||||
irb.context.irb_path = irb_path if irb_path
|
irb.context.irb_path = irb_path if irb_path
|
||||||
IRB.conf[:MAIN_CONTEXT] = irb.context
|
IRB.conf[:MAIN_CONTEXT] = irb.context
|
||||||
capture_output do
|
|
||||||
irb.eval_input
|
irb.eval_input
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -58,7 +58,9 @@ module TestIRB
|
|||||||
"irb_info",
|
"irb_info",
|
||||||
main: main
|
main: main
|
||||||
)
|
)
|
||||||
assert_empty err
|
# Because the main object is frozen, IRB would wrap a delegator around it
|
||||||
|
# Which's exit! method can't be overridden and would raise a warning
|
||||||
|
assert_match(/delegator does not forward private method #exit\!/, err)
|
||||||
assert_match(/RUBY_PLATFORM/, out)
|
assert_match(/RUBY_PLATFORM/, out)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -255,47 +255,6 @@ module TestIRB
|
|||||||
assert_match(/irb\(main\):001> next/, output)
|
assert_match(/irb\(main\):001> next/, output)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_forced_exit_finishes_process_when_nested_sessions
|
|
||||||
write_ruby <<~'ruby'
|
|
||||||
puts "First line"
|
|
||||||
puts "Second line"
|
|
||||||
binding.irb
|
|
||||||
puts "Third line"
|
|
||||||
binding.irb
|
|
||||||
puts "Fourth line"
|
|
||||||
ruby
|
|
||||||
|
|
||||||
output = run_ruby_file do
|
|
||||||
type "123"
|
|
||||||
type "456"
|
|
||||||
type "exit!"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_match(/First line\r\n/, output)
|
|
||||||
assert_match(/Second line\r\n/, output)
|
|
||||||
assert_match(/irb\(main\):001> 123/, output)
|
|
||||||
assert_match(/irb\(main\):002> 456/, output)
|
|
||||||
refute_match(/Third line\r\n/, output)
|
|
||||||
refute_match(/Fourth line\r\n/, output)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_forced_exit
|
|
||||||
write_ruby <<~'ruby'
|
|
||||||
puts "Hello"
|
|
||||||
binding.irb
|
|
||||||
ruby
|
|
||||||
|
|
||||||
output = run_ruby_file do
|
|
||||||
type "123"
|
|
||||||
type "456"
|
|
||||||
type "exit!"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_match(/Hello\r\n/, output)
|
|
||||||
assert_match(/irb\(main\):001> 123/, output)
|
|
||||||
assert_match(/irb\(main\):002> 456/, output)
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_quit
|
def test_quit
|
||||||
write_ruby <<~'RUBY'
|
write_ruby <<~'RUBY'
|
||||||
binding.irb
|
binding.irb
|
||||||
|
@ -379,20 +379,58 @@ module TestIRB
|
|||||||
HISTORY
|
HISTORY
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_history_saving_with_exit!
|
def test_nested_history_saving_from_inner_session_with_exit!
|
||||||
write_history ""
|
write_history ""
|
||||||
|
|
||||||
write_ruby <<~'RUBY'
|
write_ruby <<~'RUBY'
|
||||||
|
def foo
|
||||||
|
binding.irb
|
||||||
|
end
|
||||||
|
|
||||||
binding.irb
|
binding.irb
|
||||||
RUBY
|
RUBY
|
||||||
|
|
||||||
run_ruby_file do
|
run_ruby_file do
|
||||||
type "'starting session'"
|
type "'outer session'"
|
||||||
|
type "foo"
|
||||||
|
type "'inner session'"
|
||||||
type "exit!"
|
type "exit!"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal <<~HISTORY, @history_file.open.read
|
assert_equal <<~HISTORY, @history_file.open.read
|
||||||
'starting session'
|
'outer session'
|
||||||
|
foo
|
||||||
|
'inner session'
|
||||||
|
exit!
|
||||||
|
HISTORY
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_nested_history_saving_from_outer_session_with_exit!
|
||||||
|
write_history ""
|
||||||
|
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
def foo
|
||||||
|
binding.irb
|
||||||
|
end
|
||||||
|
|
||||||
|
binding.irb
|
||||||
|
RUBY
|
||||||
|
|
||||||
|
run_ruby_file do
|
||||||
|
type "'outer session'"
|
||||||
|
type "foo"
|
||||||
|
type "'inner session'"
|
||||||
|
type "exit"
|
||||||
|
type "'outer session again'"
|
||||||
|
type "exit!"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal <<~HISTORY, @history_file.open.read
|
||||||
|
'outer session'
|
||||||
|
foo
|
||||||
|
'inner session'
|
||||||
|
exit
|
||||||
|
'outer session again'
|
||||||
exit!
|
exit!
|
||||||
HISTORY
|
HISTORY
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user