[ruby/irb] Add commands to start and use the debugger
(https://github.com/ruby/irb/pull/449) * Seamlessly integrate a few debug commands * Improve the break command support * Utilize skip_src option if available * Add step and delete commands * Write end-to-end tests for each debugger command * Add documentation * Add backtrace, info, catch commands https://github.com/ruby/irb/commit/976100c1c2
This commit is contained in:
parent
65e31402ae
commit
c9fbc779a6
@ -96,6 +96,8 @@ require_relative "irb/easter-egg"
|
||||
# * Show the source code around binding.irb again.
|
||||
# * debug
|
||||
# * Start the debugger of debug.gem.
|
||||
# * break, delete, next, step, continue, finish, backtrace, info, catch
|
||||
# * Start the debugger of debug.gem and run the command on it.
|
||||
#
|
||||
# == Configuration
|
||||
#
|
||||
@ -470,10 +472,6 @@ module IRB
|
||||
def initialize(workspace = nil, input_method = nil)
|
||||
@context = Context.new(self, workspace, input_method)
|
||||
@context.main.extend ExtendCommandBundle
|
||||
@context.command_aliases.each do |alias_name, cmd_name|
|
||||
next if @context.symbol_alias(alias_name)
|
||||
@context.main.install_alias_method(alias_name, cmd_name)
|
||||
end
|
||||
@signal_status = :IN_IRB
|
||||
@scanner = RubyLex.new
|
||||
end
|
||||
|
21
lib/irb/cmd/backtrace.rb
Normal file
21
lib/irb/cmd/backtrace.rb
Normal file
@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Backtrace < Debug
|
||||
def self.transform_args(args)
|
||||
args&.dump
|
||||
end
|
||||
|
||||
def execute(*args)
|
||||
super(pre_cmds: ["backtrace", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
21
lib/irb/cmd/break.rb
Normal file
21
lib/irb/cmd/break.rb
Normal file
@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Break < Debug
|
||||
def self.transform_args(args)
|
||||
args&.dump
|
||||
end
|
||||
|
||||
def execute(args = nil)
|
||||
super(pre_cmds: "break #{args}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
21
lib/irb/cmd/catch.rb
Normal file
21
lib/irb/cmd/catch.rb
Normal file
@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Catch < Debug
|
||||
def self.transform_args(args)
|
||||
args&.dump
|
||||
end
|
||||
|
||||
def execute(*args)
|
||||
super(pre_cmds: ["catch", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
17
lib/irb/cmd/continue.rb
Normal file
17
lib/irb/cmd/continue.rb
Normal file
@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Continue < Debug
|
||||
def execute(*args)
|
||||
super(do_cmds: ["continue", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
@ -11,7 +11,7 @@ module IRB
|
||||
].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
|
||||
IRB_DIR = File.expand_path('..', __dir__)
|
||||
|
||||
def execute(*args)
|
||||
def execute(pre_cmds: nil, do_cmds: nil)
|
||||
unless binding_irb?
|
||||
puts "`debug` command is only available when IRB is started with binding.irb"
|
||||
return
|
||||
@ -25,11 +25,19 @@ module IRB
|
||||
return
|
||||
end
|
||||
|
||||
options = { oneshot: true, hook_call: false }
|
||||
if pre_cmds || do_cmds
|
||||
options[:command] = ['irb', pre_cmds, do_cmds]
|
||||
end
|
||||
if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
|
||||
options[:skip_src] = true
|
||||
end
|
||||
|
||||
# To make debugger commands like `next` or `continue` work without asking
|
||||
# the user to quit IRB after that, we need to exit IRB first and then hit
|
||||
# a TracePoint on #debug_break.
|
||||
file, lineno = IRB::Irb.instance_method(:debug_break).source_location
|
||||
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, oneshot: true, hook_call: false)
|
||||
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
|
||||
# exit current Irb#run call
|
||||
throw :IRB_EXIT
|
||||
end
|
||||
|
17
lib/irb/cmd/delete.rb
Normal file
17
lib/irb/cmd/delete.rb
Normal file
@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Delete < Debug
|
||||
def execute(*args)
|
||||
super(pre_cmds: ["delete", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
17
lib/irb/cmd/finish.rb
Normal file
17
lib/irb/cmd/finish.rb
Normal file
@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Finish < Debug
|
||||
def execute(*args)
|
||||
super(do_cmds: ["finish", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
@ -1,31 +1,18 @@
|
||||
# frozen_string_literal: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "nop"
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Info < Nop
|
||||
def execute
|
||||
Class.new {
|
||||
def inspect
|
||||
str = "Ruby version: #{RUBY_VERSION}\n"
|
||||
str += "IRB version: #{IRB.version}\n"
|
||||
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
||||
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
|
||||
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?
|
||||
str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
|
||||
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
||||
codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
|
||||
str += "Code page: #{codepage}\n"
|
||||
class Info < Debug
|
||||
def self.transform_args(args)
|
||||
args&.dump
|
||||
end
|
||||
str
|
||||
end
|
||||
alias_method :to_s, :inspect
|
||||
}.new
|
||||
|
||||
def execute(*args)
|
||||
super(pre_cmds: ["info", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
34
lib/irb/cmd/irb_info.rb
Normal file
34
lib/irb/cmd/irb_info.rb
Normal file
@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: false
|
||||
|
||||
require_relative "nop"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class IrbInfo < Nop
|
||||
def execute
|
||||
Class.new {
|
||||
def inspect
|
||||
str = "Ruby version: #{RUBY_VERSION}\n"
|
||||
str += "IRB version: #{IRB.version}\n"
|
||||
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
||||
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
|
||||
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?
|
||||
str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
|
||||
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
||||
codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
|
||||
str += "Code page: #{codepage}\n"
|
||||
end
|
||||
str
|
||||
end
|
||||
alias_method :to_s, :inspect
|
||||
}.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
17
lib/irb/cmd/next.rb
Normal file
17
lib/irb/cmd/next.rb
Normal file
@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Next < Debug
|
||||
def execute(*args)
|
||||
super(do_cmds: ["next", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
18
lib/irb/cmd/step.rb
Normal file
18
lib/irb/cmd/step.rb
Normal file
@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "debug"
|
||||
|
||||
module IRB
|
||||
# :stopdoc:
|
||||
|
||||
module ExtendCommand
|
||||
class Step < Debug
|
||||
def execute(*args)
|
||||
# Run `next` first to move out of binding.irb
|
||||
super(pre_cmds: "next", do_cmds: ["step", *args].join(" "))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
end
|
@ -486,9 +486,9 @@ module IRB
|
||||
@workspace.local_variable_set(:_, exception)
|
||||
end
|
||||
|
||||
# Transform a non-identifier alias (ex: @, $)
|
||||
# Transform a non-identifier alias (@, $) or keywords (next, break)
|
||||
command, args = line.split(/\s/, 2)
|
||||
if original = symbol_alias(command)
|
||||
if original = command_aliases[command.to_sym]
|
||||
line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
|
||||
command = original
|
||||
end
|
||||
@ -545,10 +545,16 @@ module IRB
|
||||
workspace.binding.local_variables
|
||||
end
|
||||
|
||||
# Return a command name if it's aliased from the argument and it's not an identifier.
|
||||
def symbol_alias(command)
|
||||
# Return true if it's aliased from the argument and it's not an identifier.
|
||||
def symbol_alias?(command)
|
||||
return nil if command.match?(/\A\w+\z/)
|
||||
command_aliases[command.to_sym]
|
||||
command_aliases.key?(command.to_sym)
|
||||
end
|
||||
|
||||
# Return true if the command supports transforming args
|
||||
def transform_args?(command)
|
||||
command = command_aliases.fetch(command.to_sym, command)
|
||||
ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -124,13 +124,48 @@ module IRB # :nodoc:
|
||||
:irb_edit, :Edit, "cmd/edit",
|
||||
[:edit, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
:irb_break, :Break, "cmd/break",
|
||||
],
|
||||
[
|
||||
:irb_catch, :Catch, "cmd/catch",
|
||||
],
|
||||
[
|
||||
:irb_next, :Next, "cmd/next",
|
||||
],
|
||||
[
|
||||
:irb_delete, :Delete, "cmd/delete",
|
||||
[:delete, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
:irb_step, :Step, "cmd/step",
|
||||
[:step, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
:irb_continue, :Continue, "cmd/continue",
|
||||
[:continue, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
:irb_finish, :Finish, "cmd/finish",
|
||||
[:finish, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
:irb_backtrace, :Backtrace, "cmd/backtrace",
|
||||
[:backtrace, NO_OVERRIDE],
|
||||
[:bt, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
:irb_debug_info, :Info, "cmd/info",
|
||||
[:info, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
[
|
||||
:irb_help, :Help, "cmd/help",
|
||||
[:help, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
[
|
||||
:irb_info, :Info, "cmd/info"
|
||||
:irb_info, :IrbInfo, "cmd/irb_info"
|
||||
],
|
||||
|
||||
[
|
||||
|
@ -160,8 +160,13 @@ module IRB # :nodoc:
|
||||
@CONF[:AT_EXIT] = []
|
||||
|
||||
@CONF[:COMMAND_ALIASES] = {
|
||||
# Symbol aliases
|
||||
:'$' => :show_source,
|
||||
:'@' => :whereami,
|
||||
# Keyword aliases
|
||||
:break => :irb_break,
|
||||
:catch => :irb_catch,
|
||||
:next => :irb_next,
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -65,9 +65,9 @@ class RubyLex
|
||||
false
|
||||
end
|
||||
else
|
||||
# Accept any single-line input starting with a non-identifier alias (ex: @, $)
|
||||
# Accept any single-line input for symbol aliases or commands that transform args
|
||||
command = code.split(/\s/, 2).first
|
||||
if context.symbol_alias(command)
|
||||
if context.symbol_alias?(command) || context.transform_args?(command)
|
||||
next true
|
||||
end
|
||||
|
||||
|
@ -17,6 +17,8 @@ begin
|
||||
@irbrc_backup = ENV['IRBRC']
|
||||
@irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc')
|
||||
File.unlink(@irbrc_file) if File.exist?(@irbrc_file)
|
||||
@ruby_file = File.join(@tmpdir, 'ruby_file.rb')
|
||||
File.unlink(@ruby_file) if File.exist?(@ruby_file)
|
||||
end
|
||||
|
||||
def teardown
|
||||
@ -235,11 +237,234 @@ begin
|
||||
EOC
|
||||
end
|
||||
|
||||
private def write_irbrc(content)
|
||||
def test_debug
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
binding.irb
|
||||
puts "Hello"
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("debug\n")
|
||||
write("next\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg) next # command
|
||||
[1, 3] in #{@ruby_file}
|
||||
1| puts "start IRB"
|
||||
2| binding.irb
|
||||
=> 3| puts "Hello"
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_break
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
binding.irb
|
||||
puts "Hello"
|
||||
puts "World"
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("break 3\n")
|
||||
write("continue\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) break 3
|
||||
#0 BP - Line #{@ruby_file}:3 (line)
|
||||
EOC
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg) continue # command
|
||||
[1, 4] in #{@ruby_file}
|
||||
1| puts "start IRB"
|
||||
2| binding.irb
|
||||
=> 3| puts "Hello"
|
||||
4| puts "World"
|
||||
=>#0 <main> at #{@ruby_file}:3
|
||||
|
||||
Stop by #0 BP - Line #{@ruby_file}:3 (line)
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_delete
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
binding.irb
|
||||
puts "Hello"
|
||||
binding.irb
|
||||
puts "World"
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("break 5\n")
|
||||
write("continue\n")
|
||||
write("delete 0\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) delete 0
|
||||
deleted: #0 BP - Line #{@ruby_file}:5 (line)
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_next
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
binding.irb
|
||||
puts "Hello"
|
||||
puts "World"
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("next\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) next
|
||||
[1, 4] in #{@ruby_file}
|
||||
1| puts "start IRB"
|
||||
2| binding.irb
|
||||
=> 3| puts "Hello"
|
||||
4| puts "World"
|
||||
=>#0 <main> at #{@ruby_file}:3
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_step
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
def foo
|
||||
puts "Hello"
|
||||
end
|
||||
binding.irb
|
||||
foo
|
||||
puts "World"
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("step\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) step
|
||||
[1, 7] in #{@ruby_file}
|
||||
1| puts "start IRB"
|
||||
2| def foo
|
||||
=> 3| puts "Hello"
|
||||
4| end
|
||||
5| binding.irb
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_continue
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
binding.irb
|
||||
puts "Hello"
|
||||
binding.irb
|
||||
puts "World"
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("continue\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) continue
|
||||
Hello
|
||||
|
||||
From: #{@ruby_file} @ line 4 :
|
||||
|
||||
1: puts "start IRB"
|
||||
2: binding.irb
|
||||
3: puts "Hello"
|
||||
=> 4: binding.irb
|
||||
5: puts "World"
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_finish
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
def foo
|
||||
binding.irb
|
||||
puts "Hello"
|
||||
end
|
||||
foo
|
||||
puts "World"
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("finish\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) finish
|
||||
Hello
|
||||
[1, 7] in #{@ruby_file}
|
||||
1| puts "start IRB"
|
||||
2| def foo
|
||||
3| binding.irb
|
||||
4| puts "Hello"
|
||||
=> 5| end
|
||||
6| foo
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_backtrace
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
def foo
|
||||
binding.irb
|
||||
end
|
||||
foo
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("backtrace\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) backtrace
|
||||
=>#0 Object#foo at #{@ruby_file}:3
|
||||
#1 <main> at #{@ruby_file}:5
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_info
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
a = 1
|
||||
binding.irb
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("info\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
(rdbg:irb) info
|
||||
%self = main
|
||||
a = 1
|
||||
EOC
|
||||
end
|
||||
|
||||
def test_catch
|
||||
write_ruby <<~'RUBY'
|
||||
puts "start IRB"
|
||||
binding.irb
|
||||
raise NotImplementedError
|
||||
RUBY
|
||||
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||
write("catch NotImplementedError\n")
|
||||
write("continue\n")
|
||||
close
|
||||
assert_include_screen(<<~EOC)
|
||||
Stop by #0 BP - Catch "NotImplementedError"
|
||||
EOC
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_include_screen(expected)
|
||||
assert_include(result.join("\n"), expected)
|
||||
end
|
||||
|
||||
def write_irbrc(content)
|
||||
File.open(@irbrc_file, 'w') do |f|
|
||||
f.write content
|
||||
end
|
||||
end
|
||||
|
||||
def write_ruby(content)
|
||||
File.open(@ruby_file, 'w') do |f|
|
||||
f.write content
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue LoadError, NameError
|
||||
# On Ruby repository, this test suit doesn't run because Ruby repo doesn't
|
||||
|
Loading…
x
Reference in New Issue
Block a user