Skip to content

Commit 4a6fabf

Browse files
committed
Support do and pre keywords in binding.irb
1 parent e91b21f commit 4a6fabf

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

lib/irb.rb

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ def CurrentContext # :nodoc:
4040
end
4141

4242
# Initializes IRB and creates a new Irb.irb object at the `TOPLEVEL_BINDING`
43-
def start(ap_path = nil)
43+
def start(ap_path = nil, **options)
4444
STDOUT.sync = true
4545
$0 = File::basename(ap_path, ".rb") if ap_path
46+
pre_cmds = options[:pre]&.rstrip
47+
do_cmds = options[:do]&.rstrip
4648

4749
setup(ap_path)
4850

@@ -51,7 +53,7 @@ def start(ap_path = nil)
5153
else
5254
irb = Irb.new
5355
end
54-
irb.run(@CONF)
56+
irb.run(@CONF, pre_cmds: pre_cmds, do_cmds: do_cmds)
5557
end
5658

5759
# Quits irb
@@ -146,7 +148,7 @@ def debug_readline(binding)
146148
input
147149
end
148150

149-
def run(conf = IRB.conf)
151+
def run(conf = IRB.conf, pre_cmds: nil, do_cmds: nil)
150152
in_nested_session = !!conf[:MAIN_CONTEXT]
151153
conf[:IRB_RC].call(context) if conf[:IRB_RC]
152154
prev_context = conf[:MAIN_CONTEXT]
@@ -169,6 +171,13 @@ def run(conf = IRB.conf)
169171
RubyVM.keep_script_lines = true
170172
end
171173

174+
if pre_cmds
175+
context.evaluate(parse_input(pre_cmds), @line_no)
176+
elsif do_cmds
177+
context.evaluate(parse_input(do_cmds), @line_no)
178+
return
179+
end
180+
172181
forced_exit = catch(:IRB_EXIT) do
173182
eval_input
174183
end
@@ -703,7 +712,7 @@ class Binding
703712
# Cooked potato: true
704713
#
705714
# See IRB for more information.
706-
def irb(show_code: true)
715+
def irb(show_code: true, **options)
707716
# Setup IRB with the current file's path and no command line arguments
708717
IRB.setup(source_location[0], argv: []) unless IRB.initialized?
709718
# Create a new workspace using the current binding
@@ -714,6 +723,8 @@ def irb(show_code: true)
714723
debugger_irb = IRB.instance_variable_get(:@debugger_irb)
715724

716725
irb_path = File.expand_path(source_location[0])
726+
pre_cmds = options[:pre]&.rstrip
727+
do_cmds = options[:do]&.rstrip
717728

718729
if debugger_irb
719730
# If we're already in a debugger session, set the workspace and irb_path for the original IRB instance
@@ -722,14 +733,14 @@ def irb(show_code: true)
722733
# If we've started a debugger session and hit another binding.irb, we don't want
723734
# to start an IRB session instead, we want to resume the irb:rdbg session.
724735
IRB::Debug.setup(debugger_irb)
725-
IRB::Debug.insert_debug_break
736+
IRB::Debug.insert_debug_break(pre_cmds: pre_cmds, do_cmds: do_cmds)
726737
debugger_irb.debug_break
727738
else
728739
# If we're not in a debugger session, create a new IRB instance with the current
729740
# workspace
730741
binding_irb = IRB::Irb.new(workspace, from_binding: true)
731742
binding_irb.context.irb_path = irb_path
732-
binding_irb.run(IRB.conf)
743+
binding_irb.run(IRB.conf, pre_cmds: pre_cmds, do_cmds: do_cmds)
733744
binding_irb.debug_break
734745
end
735746
end

test/irb/test_debugger_integration.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ def test_irb_command_can_check_local_variables
378378
type "show_source + 'Bar'"
379379
type "continue"
380380
end
381-
assert_include(output, "def start(ap_path = nil)")
381+
assert_include(output, "def start(ap_path = nil, do_cmds: nil, pre_cmds: nil)")
382382
assert_include(output, '"FooBar"')
383383
end
384384

test/irb/test_irb.rb

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,4 +947,59 @@ def bar
947947
end
948948
end
949949
end
950+
951+
class ArgumentTest < TestIRB::IntegrationTestCase
952+
def test_pre_commands
953+
write_ruby <<~'RUBY'
954+
ninty_nine = "It's a #{100 - 1}"
955+
ninty_eight = "It's a #{100 - 2}"
956+
957+
require 'irb' # need to pass an argument to binding.irb(see also: https://github.com/ruby/ruby/pull/12796)
958+
binding.irb(pre: 'p ninty_nine ;; p ninty_eight')
959+
RUBY
960+
961+
output = run_ruby_file do
962+
type "exit"
963+
end
964+
965+
assert_include output, "It's a 98"
966+
assert_include output, "It's a 99"
967+
end
968+
969+
def test_do_cmds
970+
@envs['IRB_COPY_COMMAND'] = "#{EnvUtil.rubybin} -e \"puts 'foo' + STDIN.read\""
971+
972+
write_ruby <<~'RUBY'
973+
ninty_nine = "It's a #{100 - 1}"
974+
975+
require 'irb' # need to pass an argument to binding.irb(see also: https://github.com/ruby/ruby/pull/12796)
976+
binding.irb(do: 'copy "foo"')
977+
puts ninty_nine
978+
RUBY
979+
980+
output = run_ruby_file {}
981+
982+
assert_match("foo", output)
983+
assert_match(/Copied to system clipboard/, output)
984+
assert_match("It's a 99", output)
985+
end
986+
987+
def test_pre_commands_takes_priority_over_do_commands
988+
@envs['IRB_COPY_COMMAND'] = "#{EnvUtil.rubybin} -e \"puts 'foo' + STDIN.read\""
989+
990+
write_ruby <<~'RUBY'
991+
ninty_nine = "It's a #{100 - 1}"
992+
993+
require 'irb' # need to pass an argument to binding.irb(see also: https://github.com/ruby/ruby/pull/12796)
994+
binding.irb(pre: 'p ninty_nine', do: 'copy ninty_nine')
995+
RUBY
996+
997+
output = run_ruby_file do
998+
type "exit"
999+
end
1000+
1001+
assert_not_match(/Copied to system clipboard/, output)
1002+
assert_match("It's a 99", output)
1003+
end
1004+
end
9501005
end

0 commit comments

Comments
 (0)