diff --git a/lib/irb.rb b/lib/irb.rb index 6d9c96c8f..5cd13300e 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -180,6 +180,7 @@ def run(conf = IRB.conf) trap("SIGINT", prev_trap) conf[:AT_EXIT].each{|hook| hook.call} + context.io.restore_reline_settings if context.io.respond_to?(:restore_reline_settings) context.io.save_history if save_history Kernel.exit if forced_exit end diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index b9bbdeb1e..bc6c8f6dd 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -202,6 +202,8 @@ def initialize @eof = false @completor = RegexpCompletor.new + save_readline_settings + if Readline.respond_to?("basic_word_break_characters=") Readline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS end @@ -212,6 +214,25 @@ def initialize } end + def save_readline_settings + @original_readline_settings = {} + if Readline.respond_to?("basic_word_break_characters") + @original_readline_settings[:basic_word_break_characters] = Readline.basic_word_break_characters + end + @original_readline_settings[:completion_append_character] = Readline.completion_append_character + @original_readline_settings[:completion_proc] = Readline.completion_proc + end + + def restore_reline_settings + return if !@original_readline_settings || @original_readline_settings.empty? + + if @original_readline_settings.key?(:basic_word_break_characters) && Readline.respond_to?("basic_word_break_characters=") + Readline.basic_word_break_characters = @original_readline_settings[:basic_word_break_characters] + end + Readline.completion_append_character = @original_readline_settings[:completion_append_character] + Readline.completion_proc = @original_readline_settings[:completion_proc] + end + def completion_info 'RegexpCompletor' end @@ -265,6 +286,8 @@ def initialize(completor) @eof = false @completor = completor + save_reline_settings + Reline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS Reline.completion_append_character = nil Reline.completer_quote_characters = '' @@ -288,6 +311,30 @@ def initialize(completor) end end + def save_reline_settings + @original_reline_settings = { + basic_word_break_characters: Reline.basic_word_break_characters, + completion_append_character: Reline.completion_append_character, + completer_quote_characters: Reline.completer_quote_characters, + completion_proc: Reline.completion_proc, + output_modifier_proc: Reline.output_modifier_proc, + dig_perfect_match_proc: Reline.dig_perfect_match_proc, + autocompletion: Reline.autocompletion + } + end + + def restore_reline_settings + return unless @original_reline_settings + + Reline.basic_word_break_characters = @original_reline_settings[:basic_word_break_characters] + Reline.completion_append_character = @original_reline_settings[:completion_append_character] + Reline.completer_quote_characters = @original_reline_settings[:completer_quote_characters] + Reline.completion_proc = @original_reline_settings[:completion_proc] + Reline.output_modifier_proc = @original_reline_settings[:output_modifier_proc] + Reline.dig_perfect_match_proc = @original_reline_settings[:dig_perfect_match_proc] + Reline.autocompletion = @original_reline_settings[:autocompletion] + end + def completion_info autocomplete_message = Reline.autocompletion ? 'Autocomplete' : 'Tab Complete' "#{autocomplete_message}, #{@completor.inspect}" diff --git a/test/irb/test_reline_global_leak.rb b/test/irb/test_reline_global_leak.rb new file mode 100644 index 000000000..dbf948325 --- /dev/null +++ b/test/irb/test_reline_global_leak.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true +require "irb" +require_relative "helper" + +module TestIRB + class RelineGlobalLeakTest < IntegrationTestCase + def test_reline_autocompletion_is_restored_after_irb_exit + write_ruby <<~'RUBY' + require 'reline' + + Reline.autocompletion = false + puts "Before: #{Reline.autocompletion}" + + binding.irb + + puts "After: #{Reline.autocompletion}" + RUBY + + output = run_ruby_file do + type "exit" + end + + assert_include output, "Before: false" + assert_include output, "After: false" + end + end +end