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

Allow loading multiple irb files #859

Merged
merged 1 commit into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion lib/irb/command/irb_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ def execute
str += "IRB version: #{IRB.version}\n"
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
str += "Completion: #{IRB.CurrentContext.io.respond_to?(:completion_info) ? IRB.CurrentContext.io.completion_info : 'off'}\n"
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
rc_files = IRB.rc_files.select { |rc| File.exist?(rc) }
str += ".irbrc paths: #{rc_files.join(", ")}\n" if rc_files.any?
str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
Expand Down
4 changes: 2 additions & 2 deletions lib/irb/history.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def load_history
if history_file = IRB.conf[:HISTORY_FILE]
history_file = File.expand_path(history_file)
end
history_file = IRB.rc_file("_history") unless history_file
history_file = IRB.rc_files("_history").first unless history_file
if File.exist?(history_file)
File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
f.each { |l|
Expand All @@ -41,7 +41,7 @@ def save_history
if history_file = IRB.conf[:HISTORY_FILE]
history_file = File.expand_path(history_file)
end
history_file = IRB.rc_file("_history") unless history_file
history_file = IRB.rc_files("_history").first unless history_file

# Change the permission of a file that already exists[BUG #7694]
begin
Expand Down
34 changes: 21 additions & 13 deletions lib/irb/init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -395,33 +395,41 @@ def IRB.parse_opts(argv: ::ARGV)
# Run the config file
def IRB.run_config
if @CONF[:RC]
begin
file = rc_file
rc_files.each do |rc|
# Because rc_file always returns `HOME/.irbrc` even if no rc file is present, we can't warn users about missing rc files.
# Otherwise, it'd be very noisy.
load file if File.exist?(file)
load rc if File.exist?(rc)
rescue StandardError, ScriptError => e
warn "Error loading RC file '#{file}':\n#{e.full_message(highlight: false)}"
warn "Error loading RC file '#{rc}':\n#{e.full_message(highlight: false)}"
hahmed marked this conversation as resolved.
Show resolved Hide resolved
end
end
end

IRBRC_EXT = "rc"
def IRB.rc_file(ext = IRBRC_EXT)
warn "rc_file is deprecated, please use rc_files instead."
rc_files(ext).first
end

def IRB.rc_files(ext = IRBRC_EXT)
if !@CONF[:RC_NAME_GENERATOR]
@CONF[:RC_NAME_GENERATOR] ||= []
existing_rc_file_generators = []

rc_file_generators do |rcgen|
@CONF[:RC_NAME_GENERATOR] ||= rcgen
if File.exist?(rcgen.call(IRBRC_EXT))
@CONF[:RC_NAME_GENERATOR] = rcgen
break
end
@CONF[:RC_NAME_GENERATOR] << rcgen
existing_rc_file_generators << rcgen if File.exist?(rcgen.call(ext))
end

if existing_rc_file_generators.any?
@CONF[:RC_NAME_GENERATOR] = existing_rc_file_generators
end
end
case rc_file = @CONF[:RC_NAME_GENERATOR].call(ext)
when String

@CONF[:RC_NAME_GENERATOR].map do |rc|
rc_file = rc.call(ext)
fail IllegalRCNameGenerator unless rc_file.is_a?(String)
rc_file
else
fail IllegalRCNameGenerator
end
end

Expand Down
7 changes: 4 additions & 3 deletions test/irb/test_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def teardown
def test_irb_info_multiline
FileUtils.touch("#{@tmpdir}/.inputrc")
FileUtils.touch("#{@tmpdir}/.irbrc")
FileUtils.touch("#{@tmpdir}/_irbrc")

out, err = execute_lines(
"irb_info",
Expand All @@ -86,7 +87,7 @@ def test_irb_info_multiline
IRB\sversion:\sirb\s.+\n
InputMethod:\sAbstract\sInputMethod\n
Completion: .+\n
\.irbrc\spath:\s.+\n
\.irbrc\spaths:.*\.irbrc.*_irbrc\n
RUBY_PLATFORM:\s.+\n
East\sAsian\sAmbiguous\sWidth:\s\d\n
#{@is_win ? 'Code\spage:\s\d+\n' : ''}
Expand All @@ -110,7 +111,7 @@ def test_irb_info_singleline
IRB\sversion:\sirb\s.+\n
InputMethod:\sAbstract\sInputMethod\n
Completion: .+\n
\.irbrc\spath:\s.+\n
\.irbrc\spaths:\s.+\n
RUBY_PLATFORM:\s.+\n
East\sAsian\sAmbiguous\sWidth:\s\d\n
#{@is_win ? 'Code\spage:\s\d+\n' : ''}
Expand Down Expand Up @@ -196,7 +197,7 @@ def test_irb_info_lang
IRB\sversion:\sirb .+\n
InputMethod:\sAbstract\sInputMethod\n
Completion: .+\n
\.irbrc\spath: .+\n
\.irbrc\spaths: .+\n
RUBY_PLATFORM: .+\n
LANG\senv:\sja_JP\.UTF-8\n
LC_ALL\senv:\sen_US\.UTF-8\n
Expand Down
9 changes: 5 additions & 4 deletions test/irb/test_history.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def test_history_concurrent_use_not_present
io.class::HISTORY << 'line1'
io.class::HISTORY << 'line2'

history_file = IRB.rc_file("_history")
history_file = IRB.rc_files("_history").first
assert_not_send [File, :file?, history_file]
File.write(history_file, "line0\n")
io.save_history
Expand Down Expand Up @@ -217,9 +217,10 @@ def assert_history(expected_history, initial_irb_history, input, input_method =
backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME")
IRB.conf[:LC_MESSAGES] = locale
actual_history = nil
history_file = IRB.rc_files("_history").first
Dir.mktmpdir("test_irb_history_") do |tmpdir|
ENV["HOME"] = tmpdir
File.open(IRB.rc_file("_history"), "w") do |f|
File.open(history_file, "w") do |f|
f.write(initial_irb_history)
end

Expand All @@ -229,15 +230,15 @@ def assert_history(expected_history, initial_irb_history, input, input_method =
if block_given?
previous_history = []
io.class::HISTORY.each { |line| previous_history << line }
yield IRB.rc_file("_history")
yield history_file
io.class::HISTORY.clear
previous_history.each { |line| io.class::HISTORY << line }
end
input.split.each { |line| io.class::HISTORY << line }
io.save_history

io.load_history
File.open(IRB.rc_file("_history"), "r") do |f|
File.open(history_file, "r") do |f|
actual_history = f.read
end
end
Expand Down
112 changes: 105 additions & 7 deletions test/irb/test_init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def setup
@backup_env = %w[HOME XDG_CONFIG_HOME IRBRC].each_with_object({}) do |env, hash|
hash[env] = ENV.delete(env)
end
ENV["HOME"] = @tmpdir = Dir.mktmpdir("test_irb_init_#{$$}")
ENV["HOME"] = @tmpdir = File.realpath(Dir.mktmpdir("test_irb_init_#{$$}"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by using realpath I avoid the scenario where in tests I was getting files in the absolute or sym link path, this will resolve any symbolic links, example output of rcfiles which caused this issue:

  <["/var/folders/mf/xxf7lzbx2ml7m2dx1dz8fw3c0000gn/T/test_irb_init_5716020240227-57160-q6cm7w/.irbrc",
   "/private/var/folders/mf/xxf7lzbx2ml7m2dx1dz8fw3c0000gn/T/test_irb_init_5716020240227-57160-q6cm7w/.irbrc",
   "/private/var/folders/mf/xxf7lzbx2ml7m2dx1dz8fw3c0000gn/T/test_irb_init_5716020240227-57160-q6cm7w/_irbrc",
   "/private/var/folders/mf/xxf7lzbx2ml7m2dx1dz8fw3c0000gn/T/test_irb_init_5716020240227-57160-q6cm7w/$irbrc"]> was expected to include
  <"/var/folders/mf/xxf7lzbx2ml7m2dx1dz8fw3c0000gn/T/test_irb_init_5716020240227-57160-q6cm7w/_irbrc">.

end

def teardown
Expand All @@ -35,35 +35,133 @@ def test_setup_with_minimum_argv_does_not_change_dollar0
end

def test_rc_file
verbose, $VERBOSE = $VERBOSE, nil
tmpdir = @tmpdir
Dir.chdir(tmpdir) do
ENV["XDG_CONFIG_HOME"] = "#{tmpdir}/xdg"
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
assert_equal(tmpdir+"/.irbrc", IRB.rc_file)
assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
assert_file.not_exist?(tmpdir+"/xdg")
IRB.conf[:RC_NAME_GENERATOR] = nil
FileUtils.touch(tmpdir+"/.irb#{IRB::IRBRC_EXT}")
assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
FileUtils.touch(tmpdir+"/.irbrc")
assert_equal(tmpdir+"/.irbrc", IRB.rc_file)
assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
assert_file.not_exist?(tmpdir+"/xdg")
end
ensure
$VERBOSE = verbose
end

def test_rc_file_in_subdir
verbose, $VERBOSE = $VERBOSE, nil
tmpdir = @tmpdir
Dir.chdir(tmpdir) do
FileUtils.mkdir_p("#{tmpdir}/mydir")
Dir.chdir("#{tmpdir}/mydir") do
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
assert_equal(tmpdir+"/.irbrc", IRB.rc_file)
assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
IRB.conf[:RC_NAME_GENERATOR] = nil
FileUtils.touch(tmpdir+"/.irb#{IRB::IRBRC_EXT}")
assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
FileUtils.touch(tmpdir+"/.irbrc")
assert_equal(tmpdir+"/.irbrc", IRB.rc_file)
assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
end
end
ensure
$VERBOSE = verbose
end

def test_rc_files
tmpdir = @tmpdir
Dir.chdir(tmpdir) do
ENV["XDG_CONFIG_HOME"] = "#{tmpdir}/xdg"
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_includes IRB.rc_files, tmpdir+"/.irbrc"
assert_includes IRB.rc_files("_history"), tmpdir+"/.irb_history"
assert_file.not_exist?(tmpdir+"/xdg")
IRB.conf[:RC_NAME_GENERATOR] = nil
FileUtils.touch(tmpdir+"/.irbrc")
assert_includes IRB.rc_files, tmpdir+"/.irbrc"
assert_includes IRB.rc_files("_history"), tmpdir+"/.irb_history"
assert_file.not_exist?(tmpdir+"/xdg")
end
end

def test_rc_files_in_subdir
tmpdir = @tmpdir
Dir.chdir(tmpdir) do
FileUtils.mkdir_p("#{tmpdir}/mydir")
Dir.chdir("#{tmpdir}/mydir") do
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_includes IRB.rc_files, tmpdir+"/.irbrc"
assert_includes IRB.rc_files("_history"), tmpdir+"/.irb_history"
IRB.conf[:RC_NAME_GENERATOR] = nil
FileUtils.touch(tmpdir+"/.irbrc")
assert_includes IRB.rc_files, tmpdir+"/.irbrc"
assert_includes IRB.rc_files("_history"), tmpdir+"/.irb_history"
end
end
end

def test_rc_files_has_file_from_xdg_env
tmpdir = @tmpdir
ENV["XDG_CONFIG_HOME"] = "#{tmpdir}/xdg"
xdg_config = ENV["XDG_CONFIG_HOME"]+"/irb/irbrc"

FileUtils.mkdir_p(xdg_config)

Dir.chdir(tmpdir) do
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_includes IRB.rc_files, xdg_config
end
ensure
ENV["XDG_CONFIG_HOME"] = nil
end

def test_rc_files_has_file_from_irbrc_env
tmpdir = @tmpdir
ENV["IRBRC"] = "#{tmpdir}/irb"

FileUtils.mkdir_p(ENV["IRBRC"])

Dir.chdir(tmpdir) do
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_includes IRB.rc_files, ENV["IRBRC"]
end
ensure
ENV["IRBRC"] = nil
end

def test_rc_files_has_file_from_home_env
tmpdir = @tmpdir
ENV["HOME"] = "#{tmpdir}/home"

FileUtils.mkdir_p(ENV["HOME"])

Dir.chdir(tmpdir) do
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_includes IRB.rc_files, ENV["HOME"]+"/.irbrc"
assert_includes IRB.rc_files, ENV["HOME"]+"/.config/irb/irbrc"
end
ensure
ENV["HOME"] = nil
end

def test_rc_files_contains_non_env_files
tmpdir = @tmpdir
FileUtils.mkdir_p("#{tmpdir}/.irbrc")
FileUtils.mkdir_p("#{tmpdir}/_irbrc")
FileUtils.mkdir_p("#{tmpdir}/irb.rc")
FileUtils.mkdir_p("#{tmpdir}/$irbrc")

Dir.chdir(tmpdir) do
IRB.conf[:RC_NAME_GENERATOR] = nil
assert_includes IRB.rc_files, tmpdir+"/.irbrc"
assert_includes IRB.rc_files, tmpdir+"/_irbrc"
assert_includes IRB.rc_files, tmpdir+"/irb.rc"
assert_includes IRB.rc_files, tmpdir+"/$irbrc"
end
end

def test_sigint_restore_default
Expand Down
Loading