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

Introduce exit! command #851

Merged
merged 7 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions lib/irb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,11 @@ def IRB.start(ap_path = nil)

# Quits irb
def IRB.irb_exit(*)
throw :IRB_EXIT
throw :IRB_EXIT, false
end

def IRB.irb_exit!(*)
throw :IRB_EXIT, true
end

# Aborts then interrupts irb.
Expand Down Expand Up @@ -968,7 +972,8 @@ def run(conf = IRB.conf)
conf[:IRB_RC].call(context) if conf[:IRB_RC]
conf[:MAIN_CONTEXT] = context

save_history = !in_nested_session && conf[:SAVE_HISTORY] && context.io.support_history_saving?
supports_history_saving = conf[:SAVE_HISTORY] && context.io.support_history_saving?
save_history = !in_nested_session && supports_history_saving
st0012 marked this conversation as resolved.
Show resolved Hide resolved

if save_history
context.io.load_history
Expand All @@ -979,13 +984,21 @@ def run(conf = IRB.conf)
end

begin
catch(:IRB_EXIT) do
forced_exit = false

forced_exit = catch(:IRB_EXIT) do
eval_input
end
ensure
trap("SIGINT", prev_trap)
conf[:AT_EXIT].each{|hook| hook.call}
context.io.save_history if save_history

if forced_exit
context.io.save_history if supports_history_saving
Kernel.exit!(0)
st0012 marked this conversation as resolved.
Show resolved Hide resolved
else
context.io.save_history if save_history
end
end
end

Expand Down
22 changes: 22 additions & 0 deletions lib/irb/cmd/exit_forced_action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require_relative "nop"

module IRB
# :stopdoc:

module ExtendCommand
class ExitForcedAction < Nop
category "IRB"
description "Exit the current process."

def execute(*)
IRB.irb_exit!
rescue UncaughtThrowError
Kernel.exit(0)
end
end
end

# :startdoc:
end
5 changes: 5 additions & 0 deletions lib/irb/extend-command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def irb_context
[:quit, OVERRIDE_PRIVATE_ONLY],
[:irb_quit, OVERRIDE_PRIVATE_ONLY],
],
[
:irb_exit!, :ExitForcedAction, "cmd/exit_forced_action",
[:exit!, OVERRIDE_PRIVATE_ONLY],
],

[
:irb_current_working_workspace, :CurrentWorkingWorkspace, "cmd/chws",
[:cwws, NO_OVERRIDE],
Expand Down
41 changes: 41 additions & 0 deletions test/irb/test_debug_cmd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,47 @@ def test_exit
assert_match(/irb\(main\):001> next/, output)
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
write_ruby <<~'RUBY'
binding.irb
Expand Down
18 changes: 18 additions & 0 deletions test/irb/test_history.rb
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,24 @@ def foo
HISTORY
end

def test_history_saving_with_exit!
write_history ""

write_ruby <<~'RUBY'
binding.irb
RUBY

run_ruby_file do
type "'starting session'"
type "exit!"
end

assert_equal <<~HISTORY, @history_file.open.read
'starting session'
exit!
HISTORY
end

def test_history_saving_with_nested_sessions_and_prior_history
write_history <<~HISTORY
old_history_1
Expand Down
Loading