From 429eeb09f25bd1bd3f64f70c6ef409bedd3c6c1f Mon Sep 17 00:00:00 2001 From: Ignacio Chiazzo Cardarello Date: Sat, 10 Feb 2024 19:07:48 -0300 Subject: [PATCH] [ruby/irb] Introduce exit! command (https://github.com/ruby/irb/pull/851) * 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 --------- https://github.com/ruby/irb/commit/c0a5f31679 Co-authored-by: Stan Lo --- lib/irb.rb | 21 +++++++++++++--- lib/irb/cmd/exit_forced_action.rb | 22 +++++++++++++++++ lib/irb/extend-command.rb | 5 ++++ test/irb/test_debug_cmd.rb | 41 +++++++++++++++++++++++++++++++ test/irb/test_history.rb | 18 ++++++++++++++ 5 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 lib/irb/cmd/exit_forced_action.rb diff --git a/lib/irb.rb b/lib/irb.rb index f3abed8200..ad6ec78aa4 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -886,7 +886,11 @@ module IRB # 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. @@ -968,7 +972,8 @@ module IRB 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 @@ -979,13 +984,21 @@ module IRB 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 diff --git a/lib/irb/cmd/exit_forced_action.rb b/lib/irb/cmd/exit_forced_action.rb new file mode 100644 index 0000000000..e5df75b682 --- /dev/null +++ b/lib/irb/cmd/exit_forced_action.rb @@ -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 diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb index 91ca96e91a..2db2b80578 100644 --- a/lib/irb/extend-command.rb +++ b/lib/irb/extend-command.rb @@ -36,6 +36,11 @@ module IRB # :nodoc: [: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], diff --git a/test/irb/test_debug_cmd.rb b/test/irb/test_debug_cmd.rb index 0fb45af478..cbd0120093 100644 --- a/test/irb/test_debug_cmd.rb +++ b/test/irb/test_debug_cmd.rb @@ -255,6 +255,47 @@ module TestIRB 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 diff --git a/test/irb/test_history.rb b/test/irb/test_history.rb index e6448ada37..49f3698f92 100644 --- a/test/irb/test_history.rb +++ b/test/irb/test_history.rb @@ -379,6 +379,24 @@ module TestIRB 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