Skip to content

Commit

Permalink
Introduce exit! command (#851)
Browse files Browse the repository at this point in the history
* Added failing test for when writing history on exit

* Save history on exit

* Exit early when calling Kernel.exit

* use status 0 for kernel.exit

* Added test for nested sessions

* Update lib/irb.rb

---------

Co-authored-by: Stan Lo <stan001212@gmail.com>
  • Loading branch information
ignacio-chiazzo and st0012 authored Feb 10, 2024
1 parent afe1f45 commit c0a5f31
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 4 deletions.
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

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)
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

0 comments on commit c0a5f31

Please sign in to comment.