mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
cleave test_pry into three. [Fixes #417]
This commit is contained in:
parent
c74d240d0a
commit
af5e96bf3c
3 changed files with 901 additions and 901 deletions
512
test/test_command_integration.rb
Normal file
512
test/test_command_integration.rb
Normal file
|
@ -0,0 +1,512 @@
|
|||
require 'helper'
|
||||
describe "commands" do
|
||||
it 'should interpolate ruby code into commands' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do |arg|
|
||||
arg
|
||||
end
|
||||
end
|
||||
|
||||
$test_interpolation = "bing"
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new('hello #{$test_interpolation}'), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /bing/
|
||||
$test_interpolation = nil
|
||||
end
|
||||
|
||||
# bug fix for https://github.com/pry/pry/issues/170
|
||||
it 'should not choke on complex string interpolation when checking if ruby code is a command' do
|
||||
redirect_pry_io(InputTester.new('/#{Regexp.escape(File.expand_path("."))}/'), str_output = StringIO.new) do
|
||||
pry
|
||||
end
|
||||
|
||||
str_output.string.should.not =~ /SyntaxError/
|
||||
end
|
||||
|
||||
it 'should NOT interpolate ruby code into commands if :interpolate => false' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true, :interpolate => false do |arg|
|
||||
arg
|
||||
end
|
||||
end
|
||||
|
||||
$test_interpolation = "bing"
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new('hello #{$test_interpolation}'), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /test_interpolation/
|
||||
$test_interpolation = nil
|
||||
end
|
||||
|
||||
it 'should NOT try to interpolate pure ruby code (no commands) ' do
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new('format \'#{aggy}\''), :output => str_output).rep
|
||||
str_output.string.should.not =~ /NameError/
|
||||
|
||||
Pry.new(:input => StringIO.new('format #{aggy}'), :output => str_output).rep
|
||||
str_output.string.should.not =~ /NameError/
|
||||
|
||||
$test_interpolation = "blah"
|
||||
Pry.new(:input => StringIO.new('format \'#{$test_interpolation}\''), :output => str_output).rep
|
||||
|
||||
str_output.string.should.not =~ /blah/
|
||||
$test_interpolation = nil
|
||||
end
|
||||
|
||||
it 'should create a command with a space in its name' do
|
||||
set = Pry::CommandSet.new do
|
||||
command "hello baby", "" do
|
||||
output.puts "hello baby command"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello baby", "exit-all"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello baby command/
|
||||
end
|
||||
|
||||
it 'should create a command with a space in its name and pass an argument' do
|
||||
set = Pry::CommandSet.new do
|
||||
command "hello baby", "" do |arg|
|
||||
output.puts "hello baby command #{arg}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello baby john"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello baby command john/
|
||||
end
|
||||
|
||||
it 'should create a regex command and be able to invoke it' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(.)/, "" do
|
||||
c = captures.first
|
||||
output.puts "hello#{c}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello1"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello1/
|
||||
end
|
||||
|
||||
it 'should create a regex command and pass captures into the args list before regular arguments' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(.)/, "" do |c1, a1|
|
||||
output.puts "hello #{c1} #{a1}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello1 baby"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello 1 baby/
|
||||
end
|
||||
|
||||
it 'should create a regex command and interpolate the captures' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello (.*)/, "" do |c1|
|
||||
output.puts "hello #{c1}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
$obj = "bing"
|
||||
redirect_pry_io(InputTester.new('hello #{$obj}'), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello bing/
|
||||
$obj = nil
|
||||
end
|
||||
|
||||
it 'should create a regex command and arg_string should be interpolated' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(\w+)/, "" do |c1, a1, a2, a3|
|
||||
output.puts "hello #{c1} #{a1} #{a2} #{a3}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
$a1 = "bing"
|
||||
$a2 = "bong"
|
||||
$a3 = "bang"
|
||||
redirect_pry_io(InputTester.new('hellojohn #{$a1} #{$a2} #{$a3}'), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello john bing bong bang/
|
||||
|
||||
$a1 = nil
|
||||
$a2 = nil
|
||||
$a3 = nil
|
||||
end
|
||||
|
||||
|
||||
it 'if a regex capture is missing it should be nil' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(.)?/, "" do |c1, a1|
|
||||
output.puts "hello #{c1.inspect} #{a1}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello baby"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello nil baby/
|
||||
end
|
||||
|
||||
it 'should create a command in a nested context and that command should be accessible from the parent' do
|
||||
str_output = StringIO.new
|
||||
x = "@x=nil\ncd 7\n_pry_.commands.instance_eval {\ncommand('bing') { |arg| run arg }\n}\ncd ..\nbing ls\nexit-all"
|
||||
redirect_pry_io(StringIO.new("@x=nil\ncd 7\n_pry_.commands.instance_eval {\ncommand('bing') { |arg| run arg }\n}\ncd ..\nbing ls\nexit-all"), str_output) do
|
||||
Pry.new.repl(0)
|
||||
end
|
||||
|
||||
str_output.string.should =~ /@x/
|
||||
end
|
||||
|
||||
it 'should define a command that keeps its return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
:kept_hello
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /:kept_hello/
|
||||
str_output.string.should =~ /=>/
|
||||
end
|
||||
|
||||
it 'should define a command that does NOT keep its return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => false do
|
||||
:kept_hello
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
(str_output.string =~ /:kept_hello/).should == nil
|
||||
str_output.string !~ /=>/
|
||||
end
|
||||
|
||||
it 'should define a command that keeps its return value even when nil' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
nil
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /nil/
|
||||
str_output.string.should =~ /=>/
|
||||
end
|
||||
|
||||
it 'should define a command that keeps its return value but does not return when value is void' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
void
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.empty?.should == true
|
||||
end
|
||||
|
||||
it 'a command (with :keep_retval => false) that replaces eval_string with a valid expression should not have the expression value suppressed' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "" do
|
||||
eval_string.replace("6")
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /6/
|
||||
end
|
||||
|
||||
|
||||
it 'a command (with :keep_retval => true) that replaces eval_string with a valid expression should overwrite the eval_string with the return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
eval_string.replace("6")
|
||||
7
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /7/
|
||||
str_output.string.should.not =~ /6/
|
||||
end
|
||||
|
||||
it 'a command that return a value in a multi-line expression should clear the expression and return the value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
5
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /5/
|
||||
end
|
||||
|
||||
|
||||
it 'should set the commands default, and the default should be overridable' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello" do
|
||||
output.puts "hello world"
|
||||
end
|
||||
end
|
||||
|
||||
Pry.commands = klass
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("hello"), :output => str_output).rep
|
||||
str_output.string.should =~ /hello world/
|
||||
|
||||
other_klass = Pry::CommandSet.new do
|
||||
command "goodbye", "" do
|
||||
output.puts "goodbye world"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
|
||||
Pry.new(:input => InputTester.new("goodbye"), :output => str_output, :commands => other_klass).rep
|
||||
str_output.string.should =~ /goodbye world/
|
||||
end
|
||||
|
||||
it 'should inherit "help" command from Pry::CommandBase' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "h", "h command" do
|
||||
end
|
||||
end
|
||||
|
||||
klass.commands.keys.size.should == 3
|
||||
klass.commands.keys.include?("help").should == true
|
||||
klass.commands.keys.include?("install-command").should == true
|
||||
klass.commands.keys.include?("h").should == true
|
||||
end
|
||||
|
||||
it 'should inherit commands from Pry::Commands' do
|
||||
klass = Pry::CommandSet.new Pry::Commands do
|
||||
command "v" do
|
||||
end
|
||||
end
|
||||
|
||||
klass.commands.include?("nesting").should == true
|
||||
klass.commands.include?("jump-to").should == true
|
||||
klass.commands.include?("cd").should == true
|
||||
klass.commands.include?("v").should == true
|
||||
end
|
||||
|
||||
it 'should alias a command with another command' do
|
||||
klass = Pry::CommandSet.new do
|
||||
alias_command "help2", "help"
|
||||
end
|
||||
klass.commands["help2"].block.should == klass.commands["help"].block
|
||||
end
|
||||
|
||||
it 'should change description of a command using desc' do
|
||||
klass = Pry::CommandSet.new do; end
|
||||
orig = klass.commands["help"].description
|
||||
klass.instance_eval do
|
||||
desc "help", "blah"
|
||||
end
|
||||
klass.commands["help"].description.should.not == orig
|
||||
klass.commands["help"].description.should == "blah"
|
||||
end
|
||||
|
||||
it 'should run a command from within a command' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "v" do
|
||||
output.puts "v command"
|
||||
end
|
||||
|
||||
command "run_v" do
|
||||
run "v"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("run_v"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /v command/
|
||||
end
|
||||
|
||||
it 'should run a regex command from within a command' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command /v(.*)?/ do |arg|
|
||||
output.puts "v #{arg}"
|
||||
end
|
||||
|
||||
command "run_v" do
|
||||
run "vbaby"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("run_v"), str_output) do
|
||||
Pry.new(:commands => klass).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /v baby/
|
||||
end
|
||||
|
||||
it 'should run a command from within a command with arguments' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command /v(\w+)/ do |arg1, arg2|
|
||||
output.puts "v #{arg1} #{arg2}"
|
||||
end
|
||||
|
||||
command "run_v_explicit_parameter" do
|
||||
run "vbaby", "param"
|
||||
end
|
||||
|
||||
command "run_v_embedded_parameter" do
|
||||
run "vbaby param"
|
||||
end
|
||||
end
|
||||
|
||||
["run_v_explicit_parameter", "run_v_embedded_parameter"].each do |cmd|
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new(cmd), str_output) do
|
||||
Pry.new(:commands => klass).rep
|
||||
end
|
||||
str_output.string.should =~ /v baby param/
|
||||
end
|
||||
end
|
||||
|
||||
it 'should enable an inherited method to access opts and output and target, due to instance_exec' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "v" do
|
||||
output.puts "#{target.eval('self')}"
|
||||
end
|
||||
end
|
||||
|
||||
child_klass = Pry::CommandSet.new klass do
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:print => proc {}, :input => InputTester.new("v"),
|
||||
:output => str_output, :commands => child_klass).rep("john")
|
||||
|
||||
str_output.string.rstrip.should == "john"
|
||||
end
|
||||
|
||||
it 'should import commands from another command object' do
|
||||
klass = Pry::CommandSet.new do
|
||||
import_from Pry::Commands, "ls", "jump-to"
|
||||
end
|
||||
|
||||
klass.commands.include?("ls").should == true
|
||||
klass.commands.include?("jump-to").should == true
|
||||
end
|
||||
|
||||
it 'should delete some inherited commands when using delete method' do
|
||||
klass = Pry::CommandSet.new Pry::Commands do
|
||||
command "v" do
|
||||
end
|
||||
|
||||
delete "show-doc", "show-method"
|
||||
delete "ls"
|
||||
end
|
||||
|
||||
klass.commands.include?("nesting").should == true
|
||||
klass.commands.include?("jump-to").should == true
|
||||
klass.commands.include?("cd").should == true
|
||||
klass.commands.include?("v").should == true
|
||||
klass.commands.include?("show-doc").should == false
|
||||
klass.commands.include?("show-method").should == false
|
||||
klass.commands.include?("ls").should == false
|
||||
end
|
||||
|
||||
it 'should override some inherited commands' do
|
||||
klass = Pry::CommandSet.new Pry::Commands do
|
||||
command "jump-to" do
|
||||
output.puts "jump-to the music"
|
||||
end
|
||||
|
||||
command "help" do
|
||||
output.puts "help to the music"
|
||||
end
|
||||
end
|
||||
|
||||
# suppress evaluation output
|
||||
Pry.print = proc {}
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("jump-to"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.rstrip.should == "jump-to the music"
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("help"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.rstrip.should == "help to the music"
|
||||
|
||||
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
|
||||
it 'should run a command with no parameter' do
|
||||
pry_tester = Pry.new
|
||||
pry_tester.commands = CommandTester
|
||||
pry_tester.input = InputTester.new("command1", "exit-all")
|
||||
pry_tester.commands = CommandTester
|
||||
|
||||
str_output = StringIO.new
|
||||
pry_tester.output = str_output
|
||||
|
||||
pry_tester.rep
|
||||
|
||||
str_output.string.should =~ /command1/
|
||||
end
|
||||
|
||||
it 'should run a command with one parameter' do
|
||||
pry_tester = Pry.new
|
||||
pry_tester.commands = CommandTester
|
||||
pry_tester.input = InputTester.new("command2 horsey", "exit-all")
|
||||
pry_tester.commands = CommandTester
|
||||
|
||||
str_output = StringIO.new
|
||||
pry_tester.output = str_output
|
||||
|
||||
pry_tester.rep
|
||||
|
||||
str_output.string.should =~ /horsey/
|
||||
end
|
||||
end
|
||||
|
||||
describe "Pry#run_command" do
|
||||
it 'should run a command in a specified context' do
|
||||
b = Pry.binding_for(7)
|
||||
p = Pry.new(:output => StringIO.new)
|
||||
p.run_command("ls -m", "", b)
|
||||
p.output.string.should =~ /divmod/
|
||||
end
|
||||
|
||||
it 'should run a command that modifies the passed in eval_string' do
|
||||
b = Pry.binding_for(7)
|
||||
p = Pry.new(:output => StringIO.new)
|
||||
eval_string = "def hello\npeter pan\n"
|
||||
p.run_command("amend-line !", eval_string, b)
|
||||
eval_string.should =~ /def hello/
|
||||
eval_string.should.not =~ /peter pan/
|
||||
end
|
||||
|
||||
it 'should run a command in the context of a session' do
|
||||
mock_pry("@session_ivar = 10", "_pry_.run_command('ls')").should =~ /@session_ivar/
|
||||
end
|
||||
end
|
||||
|
||||
|
910
test/test_pry.rb
910
test/test_pry.rb
|
@ -170,28 +170,6 @@ describe Pry do
|
|||
end
|
||||
end
|
||||
|
||||
describe "Pry#run_command" do
|
||||
it 'should run a command in a specified context' do
|
||||
b = Pry.binding_for(7)
|
||||
p = Pry.new(:output => StringIO.new)
|
||||
p.run_command("ls -m", "", b)
|
||||
p.output.string.should =~ /divmod/
|
||||
end
|
||||
|
||||
it 'should run a command that modifies the passed in eval_string' do
|
||||
b = Pry.binding_for(7)
|
||||
p = Pry.new(:output => StringIO.new)
|
||||
eval_string = "def hello\npeter pan\n"
|
||||
p.run_command("amend-line !", eval_string, b)
|
||||
eval_string.should =~ /def hello/
|
||||
eval_string.should.not =~ /peter pan/
|
||||
end
|
||||
|
||||
it 'should run a command in the context of a session' do
|
||||
mock_pry("@session_ivar = 10", "_pry_.run_command('ls')").should =~ /@session_ivar/
|
||||
end
|
||||
end
|
||||
|
||||
describe "repl" do
|
||||
describe "basic functionality" do
|
||||
it 'should set an ivar on an object and exit the repl' do
|
||||
|
@ -408,36 +386,6 @@ describe Pry do
|
|||
end
|
||||
end
|
||||
|
||||
describe "commands" do
|
||||
it 'should run a command with no parameter' do
|
||||
pry_tester = Pry.new
|
||||
pry_tester.commands = CommandTester
|
||||
pry_tester.input = InputTester.new("command1", "exit-all")
|
||||
pry_tester.commands = CommandTester
|
||||
|
||||
str_output = StringIO.new
|
||||
pry_tester.output = str_output
|
||||
|
||||
pry_tester.rep
|
||||
|
||||
str_output.string.should =~ /command1/
|
||||
end
|
||||
|
||||
it 'should run a command with one parameter' do
|
||||
pry_tester = Pry.new
|
||||
pry_tester.commands = CommandTester
|
||||
pry_tester.input = InputTester.new("command2 horsey", "exit-all")
|
||||
pry_tester.commands = CommandTester
|
||||
|
||||
str_output = StringIO.new
|
||||
pry_tester.output = str_output
|
||||
|
||||
pry_tester.rep
|
||||
|
||||
str_output.string.should =~ /horsey/
|
||||
end
|
||||
end
|
||||
|
||||
describe "Object#pry" do
|
||||
|
||||
after do
|
||||
|
@ -480,854 +428,14 @@ describe Pry do
|
|||
Pry.binding_for(_main_.call).should == Pry.binding_for(_main_.call)
|
||||
end
|
||||
end
|
||||
|
||||
describe "test Pry defaults" do
|
||||
|
||||
after do
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
|
||||
describe "input" do
|
||||
|
||||
after do
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
|
||||
it 'should set the input default, and the default should be overridable' do
|
||||
Pry.input = InputTester.new("5")
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.output = str_output
|
||||
Pry.new.rep
|
||||
str_output.string.should =~ /5/
|
||||
|
||||
Pry.new(:input => InputTester.new("6")).rep
|
||||
str_output.string.should =~ /6/
|
||||
end
|
||||
|
||||
it 'should pass in the prompt if readline arity is 1' do
|
||||
Pry.prompt = proc { "A" }
|
||||
|
||||
arity_one_input = Class.new do
|
||||
attr_accessor :prompt
|
||||
def readline(prompt)
|
||||
@prompt = prompt
|
||||
"exit-all"
|
||||
end
|
||||
end.new
|
||||
|
||||
Pry.start(self, :input => arity_one_input, :output => Pry::NullOutput)
|
||||
arity_one_input.prompt.should == Pry.prompt.call
|
||||
end
|
||||
|
||||
it 'should not pass in the prompt if the arity is 0' do
|
||||
Pry.prompt = proc { "A" }
|
||||
|
||||
arity_zero_input = Class.new do
|
||||
def readline
|
||||
"exit-all"
|
||||
end
|
||||
end.new
|
||||
|
||||
lambda { Pry.start(self, :input => arity_zero_input, :output => Pry::NullOutput) }.should.not.raise Exception
|
||||
end
|
||||
|
||||
it 'should not pass in the prompt if the arity is -1' do
|
||||
Pry.prompt = proc { "A" }
|
||||
|
||||
arity_multi_input = Class.new do
|
||||
attr_accessor :prompt
|
||||
|
||||
def readline(*args)
|
||||
@prompt = args.first
|
||||
"exit-all"
|
||||
end
|
||||
end.new
|
||||
|
||||
Pry.start(self, :input => arity_multi_input, :output => Pry::NullOutput)
|
||||
arity_multi_input.prompt.should == nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it 'should set the output default, and the default should be overridable' do
|
||||
Pry.input = InputTester.new("5", "6", "7")
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.output = str_output
|
||||
|
||||
Pry.new.rep
|
||||
str_output.string.should =~ /5/
|
||||
|
||||
Pry.new.rep
|
||||
str_output.string.should =~ /5\n.*6/
|
||||
|
||||
str_output2 = StringIO.new
|
||||
Pry.new(:output => str_output2).rep
|
||||
str_output2.string.should.not =~ /5\n.*6/
|
||||
str_output2.string.should =~ /7/
|
||||
end
|
||||
|
||||
describe "commands" do
|
||||
it 'should interpolate ruby code into commands' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do |arg|
|
||||
arg
|
||||
end
|
||||
end
|
||||
|
||||
$test_interpolation = "bing"
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new('hello #{$test_interpolation}'), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /bing/
|
||||
$test_interpolation = nil
|
||||
end
|
||||
|
||||
# bug fix for https://github.com/pry/pry/issues/170
|
||||
it 'should not choke on complex string interpolation when checking if ruby code is a command' do
|
||||
redirect_pry_io(InputTester.new('/#{Regexp.escape(File.expand_path("."))}/'), str_output = StringIO.new) do
|
||||
pry
|
||||
end
|
||||
|
||||
str_output.string.should.not =~ /SyntaxError/
|
||||
end
|
||||
|
||||
it 'should NOT interpolate ruby code into commands if :interpolate => false' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true, :interpolate => false do |arg|
|
||||
arg
|
||||
end
|
||||
end
|
||||
|
||||
$test_interpolation = "bing"
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new('hello #{$test_interpolation}'), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /test_interpolation/
|
||||
$test_interpolation = nil
|
||||
end
|
||||
|
||||
it 'should NOT try to interpolate pure ruby code (no commands) ' do
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new('format \'#{aggy}\''), :output => str_output).rep
|
||||
str_output.string.should.not =~ /NameError/
|
||||
|
||||
Pry.new(:input => StringIO.new('format #{aggy}'), :output => str_output).rep
|
||||
str_output.string.should.not =~ /NameError/
|
||||
|
||||
$test_interpolation = "blah"
|
||||
Pry.new(:input => StringIO.new('format \'#{$test_interpolation}\''), :output => str_output).rep
|
||||
|
||||
str_output.string.should.not =~ /blah/
|
||||
$test_interpolation = nil
|
||||
end
|
||||
|
||||
it 'should create a command with a space in its name' do
|
||||
set = Pry::CommandSet.new do
|
||||
command "hello baby", "" do
|
||||
output.puts "hello baby command"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello baby", "exit-all"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello baby command/
|
||||
end
|
||||
|
||||
it 'should create a command with a space in its name and pass an argument' do
|
||||
set = Pry::CommandSet.new do
|
||||
command "hello baby", "" do |arg|
|
||||
output.puts "hello baby command #{arg}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello baby john"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello baby command john/
|
||||
end
|
||||
|
||||
it 'should create a regex command and be able to invoke it' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(.)/, "" do
|
||||
c = captures.first
|
||||
output.puts "hello#{c}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello1"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello1/
|
||||
end
|
||||
|
||||
it 'should create a regex command and pass captures into the args list before regular arguments' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(.)/, "" do |c1, a1|
|
||||
output.puts "hello #{c1} #{a1}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello1 baby"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello 1 baby/
|
||||
end
|
||||
|
||||
it 'should create a regex command and interpolate the captures' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello (.*)/, "" do |c1|
|
||||
output.puts "hello #{c1}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
$obj = "bing"
|
||||
redirect_pry_io(InputTester.new('hello #{$obj}'), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello bing/
|
||||
$obj = nil
|
||||
end
|
||||
|
||||
it 'should create a regex command and arg_string should be interpolated' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(\w+)/, "" do |c1, a1, a2, a3|
|
||||
output.puts "hello #{c1} #{a1} #{a2} #{a3}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
$a1 = "bing"
|
||||
$a2 = "bong"
|
||||
$a3 = "bang"
|
||||
redirect_pry_io(InputTester.new('hellojohn #{$a1} #{$a2} #{$a3}'), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello john bing bong bang/
|
||||
|
||||
$a1 = nil
|
||||
$a2 = nil
|
||||
$a3 = nil
|
||||
end
|
||||
|
||||
|
||||
it 'if a regex capture is missing it should be nil' do
|
||||
set = Pry::CommandSet.new do
|
||||
command /hello(.)?/, "" do |c1, a1|
|
||||
output.puts "hello #{c1.inspect} #{a1}"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("hello baby"), str_output) do
|
||||
Pry.new(:commands => set).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /hello nil baby/
|
||||
end
|
||||
|
||||
it 'should create a command in a nested context and that command should be accessible from the parent' do
|
||||
str_output = StringIO.new
|
||||
x = "@x=nil\ncd 7\n_pry_.commands.instance_eval {\ncommand('bing') { |arg| run arg }\n}\ncd ..\nbing ls\nexit-all"
|
||||
redirect_pry_io(StringIO.new("@x=nil\ncd 7\n_pry_.commands.instance_eval {\ncommand('bing') { |arg| run arg }\n}\ncd ..\nbing ls\nexit-all"), str_output) do
|
||||
Pry.new.repl(0)
|
||||
end
|
||||
|
||||
str_output.string.should =~ /@x/
|
||||
end
|
||||
|
||||
it 'should define a command that keeps its return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
:kept_hello
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /:kept_hello/
|
||||
str_output.string.should =~ /=>/
|
||||
end
|
||||
|
||||
it 'should define a command that does NOT keep its return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => false do
|
||||
:kept_hello
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
(str_output.string =~ /:kept_hello/).should == nil
|
||||
str_output.string !~ /=>/
|
||||
end
|
||||
|
||||
it 'should define a command that keeps its return value even when nil' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
nil
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /nil/
|
||||
str_output.string.should =~ /=>/
|
||||
end
|
||||
|
||||
it 'should define a command that keeps its return value but does not return when value is void' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
void
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("hello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.empty?.should == true
|
||||
end
|
||||
|
||||
it 'a command (with :keep_retval => false) that replaces eval_string with a valid expression should not have the expression value suppressed' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "" do
|
||||
eval_string.replace("6")
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /6/
|
||||
end
|
||||
|
||||
|
||||
it 'a command (with :keep_retval => true) that replaces eval_string with a valid expression should overwrite the eval_string with the return value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
eval_string.replace("6")
|
||||
7
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /7/
|
||||
str_output.string.should.not =~ /6/
|
||||
end
|
||||
|
||||
it 'a command that return a value in a multi-line expression should clear the expression and return the value' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello", "", :keep_retval => true do
|
||||
5
|
||||
end
|
||||
end
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => StringIO.new("def yo\nhello\n"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /5/
|
||||
end
|
||||
|
||||
|
||||
it 'should set the commands default, and the default should be overridable' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "hello" do
|
||||
output.puts "hello world"
|
||||
end
|
||||
end
|
||||
|
||||
Pry.commands = klass
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("hello"), :output => str_output).rep
|
||||
str_output.string.should =~ /hello world/
|
||||
|
||||
other_klass = Pry::CommandSet.new do
|
||||
command "goodbye", "" do
|
||||
output.puts "goodbye world"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
|
||||
Pry.new(:input => InputTester.new("goodbye"), :output => str_output, :commands => other_klass).rep
|
||||
str_output.string.should =~ /goodbye world/
|
||||
end
|
||||
|
||||
it 'should inherit "help" command from Pry::CommandBase' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "h", "h command" do
|
||||
end
|
||||
end
|
||||
|
||||
klass.commands.keys.size.should == 3
|
||||
klass.commands.keys.include?("help").should == true
|
||||
klass.commands.keys.include?("install-command").should == true
|
||||
klass.commands.keys.include?("h").should == true
|
||||
end
|
||||
|
||||
it 'should inherit commands from Pry::Commands' do
|
||||
klass = Pry::CommandSet.new Pry::Commands do
|
||||
command "v" do
|
||||
end
|
||||
end
|
||||
|
||||
klass.commands.include?("nesting").should == true
|
||||
klass.commands.include?("jump-to").should == true
|
||||
klass.commands.include?("cd").should == true
|
||||
klass.commands.include?("v").should == true
|
||||
end
|
||||
|
||||
it 'should alias a command with another command' do
|
||||
klass = Pry::CommandSet.new do
|
||||
alias_command "help2", "help"
|
||||
end
|
||||
klass.commands["help2"].block.should == klass.commands["help"].block
|
||||
end
|
||||
|
||||
it 'should change description of a command using desc' do
|
||||
klass = Pry::CommandSet.new do; end
|
||||
orig = klass.commands["help"].description
|
||||
klass.instance_eval do
|
||||
desc "help", "blah"
|
||||
end
|
||||
klass.commands["help"].description.should.not == orig
|
||||
klass.commands["help"].description.should == "blah"
|
||||
end
|
||||
|
||||
it 'should run a command from within a command' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "v" do
|
||||
output.puts "v command"
|
||||
end
|
||||
|
||||
command "run_v" do
|
||||
run "v"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("run_v"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.should =~ /v command/
|
||||
end
|
||||
|
||||
it 'should run a regex command from within a command' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command /v(.*)?/ do |arg|
|
||||
output.puts "v #{arg}"
|
||||
end
|
||||
|
||||
command "run_v" do
|
||||
run "vbaby"
|
||||
end
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new("run_v"), str_output) do
|
||||
Pry.new(:commands => klass).rep
|
||||
end
|
||||
|
||||
str_output.string.should =~ /v baby/
|
||||
end
|
||||
|
||||
it 'should run a command from within a command with arguments' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command /v(\w+)/ do |arg1, arg2|
|
||||
output.puts "v #{arg1} #{arg2}"
|
||||
end
|
||||
|
||||
command "run_v_explicit_parameter" do
|
||||
run "vbaby", "param"
|
||||
end
|
||||
|
||||
command "run_v_embedded_parameter" do
|
||||
run "vbaby param"
|
||||
end
|
||||
end
|
||||
|
||||
["run_v_explicit_parameter", "run_v_embedded_parameter"].each do |cmd|
|
||||
str_output = StringIO.new
|
||||
redirect_pry_io(InputTester.new(cmd), str_output) do
|
||||
Pry.new(:commands => klass).rep
|
||||
end
|
||||
str_output.string.should =~ /v baby param/
|
||||
end
|
||||
end
|
||||
|
||||
it 'should enable an inherited method to access opts and output and target, due to instance_exec' do
|
||||
klass = Pry::CommandSet.new do
|
||||
command "v" do
|
||||
output.puts "#{target.eval('self')}"
|
||||
end
|
||||
end
|
||||
|
||||
child_klass = Pry::CommandSet.new klass do
|
||||
end
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:print => proc {}, :input => InputTester.new("v"),
|
||||
:output => str_output, :commands => child_klass).rep("john")
|
||||
|
||||
str_output.string.rstrip.should == "john"
|
||||
end
|
||||
|
||||
it 'should import commands from another command object' do
|
||||
klass = Pry::CommandSet.new do
|
||||
import_from Pry::Commands, "ls", "jump-to"
|
||||
end
|
||||
|
||||
klass.commands.include?("ls").should == true
|
||||
klass.commands.include?("jump-to").should == true
|
||||
end
|
||||
|
||||
it 'should delete some inherited commands when using delete method' do
|
||||
klass = Pry::CommandSet.new Pry::Commands do
|
||||
command "v" do
|
||||
end
|
||||
|
||||
delete "show-doc", "show-method"
|
||||
delete "ls"
|
||||
end
|
||||
|
||||
klass.commands.include?("nesting").should == true
|
||||
klass.commands.include?("jump-to").should == true
|
||||
klass.commands.include?("cd").should == true
|
||||
klass.commands.include?("v").should == true
|
||||
klass.commands.include?("show-doc").should == false
|
||||
klass.commands.include?("show-method").should == false
|
||||
klass.commands.include?("ls").should == false
|
||||
end
|
||||
|
||||
it 'should override some inherited commands' do
|
||||
klass = Pry::CommandSet.new Pry::Commands do
|
||||
command "jump-to" do
|
||||
output.puts "jump-to the music"
|
||||
end
|
||||
|
||||
command "help" do
|
||||
output.puts "help to the music"
|
||||
end
|
||||
end
|
||||
|
||||
# suppress evaluation output
|
||||
Pry.print = proc {}
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("jump-to"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.rstrip.should == "jump-to the music"
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("help"), :output => str_output, :commands => klass).rep
|
||||
str_output.string.rstrip.should == "help to the music"
|
||||
|
||||
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
end
|
||||
|
||||
it "should set the print default, and the default should be overridable" do
|
||||
new_print = proc { |out, value| out.puts value }
|
||||
Pry.print = new_print
|
||||
|
||||
Pry.new.print.should == Pry.print
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("\"test\""), :output => str_output).rep
|
||||
str_output.string.should == "test\n"
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("\"test\""), :output => str_output,
|
||||
:print => proc { |out, value| out.puts value.reverse }).rep
|
||||
str_output.string.should == "tset\n"
|
||||
|
||||
Pry.new.print.should == Pry.print
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("\"test\""), :output => str_output).rep
|
||||
str_output.string.should == "test\n"
|
||||
end
|
||||
|
||||
describe "pry return values" do
|
||||
it 'should return nil' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all"), :output => Pry::NullOutput).should == nil
|
||||
end
|
||||
|
||||
it 'should return the parameter given to exit-all' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all 10"), :output => Pry::NullOutput).should == 10
|
||||
end
|
||||
|
||||
it 'should return the parameter (multi word string) given to exit-all' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all \"john mair\""), :output => Pry::NullOutput).should == "john mair"
|
||||
end
|
||||
|
||||
it 'should return the parameter (function call) given to exit-all' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all 'abc'.reverse"), :output => Pry::NullOutput).should == 'cba'
|
||||
end
|
||||
|
||||
it 'should return the parameter (self) given to exit-all' do
|
||||
Pry.start("carl", :input => StringIO.new("exit-all self"), :output => Pry::NullOutput).should == "carl"
|
||||
end
|
||||
end
|
||||
|
||||
describe "prompts" do
|
||||
before do
|
||||
@empty_input_buffer = ""
|
||||
@non_empty_input_buffer = "def hello"
|
||||
@context = Pry.binding_for(0)
|
||||
end
|
||||
|
||||
it 'should set the prompt default, and the default should be overridable (single prompt)' do
|
||||
new_prompt = proc { "test prompt> " }
|
||||
Pry.prompt = new_prompt
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt> "
|
||||
|
||||
new_prompt = proc { "A" }
|
||||
pry_tester = Pry.new(:prompt => new_prompt)
|
||||
pry_tester.prompt.should == new_prompt
|
||||
pry_tester.select_prompt(@empty_input_buffer, @context).should == "A"
|
||||
pry_tester.select_prompt(@non_empty_input_buffer, @context).should == "A"
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt> "
|
||||
end
|
||||
|
||||
it 'should set the prompt default, and the default should be overridable (multi prompt)' do
|
||||
new_prompt = [proc { "test prompt> " }, proc { "test prompt* " }]
|
||||
Pry.prompt = new_prompt
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt* "
|
||||
|
||||
new_prompt = [proc { "A" }, proc { "B" }]
|
||||
pry_tester = Pry.new(:prompt => new_prompt)
|
||||
pry_tester.prompt.should == new_prompt
|
||||
pry_tester.select_prompt(@empty_input_buffer, @context).should == "A"
|
||||
pry_tester.select_prompt(@non_empty_input_buffer, @context).should == "B"
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt* "
|
||||
end
|
||||
|
||||
describe 'storing and restoring the prompt' do
|
||||
before do
|
||||
make = lambda do |name,i|
|
||||
prompt = [ proc { "#{i}>" } , proc { "#{i+1}>" } ]
|
||||
(class << prompt; self; end).send(:define_method, :inspect) { "<Prompt-#{name}>" }
|
||||
prompt
|
||||
end
|
||||
@a , @b , @c = make[:a,0] , make[:b,1] , make[:c,2]
|
||||
@pry = Pry.new :prompt => @a
|
||||
end
|
||||
it 'should have a prompt stack' do
|
||||
@pry.push_prompt @b
|
||||
@pry.push_prompt @c
|
||||
@pry.prompt.should == @c
|
||||
@pry.pop_prompt
|
||||
@pry.prompt.should == @b
|
||||
@pry.pop_prompt
|
||||
@pry.prompt.should == @a
|
||||
end
|
||||
|
||||
it 'should restore overridden prompts when returning from file-mode' do
|
||||
pry = Pry.new :input => InputTester.new('shell-mode', 'shell-mode'),
|
||||
:prompt => [ proc { 'P>' } ] * 2
|
||||
pry.select_prompt(@empty_input_buffer, @context).should == "P>"
|
||||
pry.re
|
||||
pry.select_prompt(@empty_input_buffer, @context).should =~ /\Apry .* \$ \z/
|
||||
pry.re
|
||||
pry.select_prompt(@empty_input_buffer, @context).should == "P>"
|
||||
end
|
||||
|
||||
it '#pop_prompt should return the popped prompt' do
|
||||
@pry.push_prompt @b
|
||||
@pry.push_prompt @c
|
||||
@pry.pop_prompt.should == @c
|
||||
@pry.pop_prompt.should == @b
|
||||
end
|
||||
|
||||
it 'should not pop the last prompt' do
|
||||
@pry.push_prompt @b
|
||||
@pry.pop_prompt.should == @b
|
||||
@pry.pop_prompt.should == @a
|
||||
@pry.pop_prompt.should == @a
|
||||
@pry.prompt.should == @a
|
||||
end
|
||||
|
||||
describe '#prompt= should replace the current prompt with the new prompt' do
|
||||
it 'when only one prompt on the stack' do
|
||||
@pry.prompt = @b
|
||||
@pry.prompt.should == @b
|
||||
@pry.pop_prompt.should == @b
|
||||
@pry.pop_prompt.should == @b
|
||||
end
|
||||
it 'when several prompts on the stack' do
|
||||
@pry.push_prompt @b
|
||||
@pry.prompt = @c
|
||||
@pry.pop_prompt.should == @c
|
||||
@pry.pop_prompt.should == @a
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "view_clip used for displaying an object in a truncated format" do
|
||||
|
||||
VC_MAX_LENGTH = 60
|
||||
|
||||
describe "given an object with an #inspect string" do
|
||||
it "returns the #<> format of the object (never use inspect)" do
|
||||
o = Object.new
|
||||
def o.inspect; "a" * VC_MAX_LENGTH; end
|
||||
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<Object/
|
||||
end
|
||||
end
|
||||
|
||||
describe "given the 'main' object" do
|
||||
it "returns the #to_s of main (special case)" do
|
||||
o = TOPLEVEL_BINDING.eval('self')
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should == o.to_s
|
||||
end
|
||||
end
|
||||
|
||||
describe "given the a Numeric, String or Symbol object" do
|
||||
[1, 2.0, -5, "hello", :test].each do |o|
|
||||
it "returns the #inspect of the special-cased immediate object: #{o}" do
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should == o.inspect
|
||||
end
|
||||
end
|
||||
|
||||
# only testing with String here :)
|
||||
it "returns #<> format of the special-cased immediate object if #inspect is longer than maximum" do
|
||||
o = "o" * (VC_MAX_LENGTH + 1)
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<String/
|
||||
end
|
||||
end
|
||||
|
||||
describe "given an object with an #inspect string as long as the maximum specified" do
|
||||
it "returns the #<> format of the object (never use inspect)" do
|
||||
o = Object.new
|
||||
def o.inspect; "a" * VC_MAX_LENGTH; end
|
||||
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<Object/
|
||||
end
|
||||
end
|
||||
|
||||
describe "given a regular object with an #inspect string longer than the maximum specified" do
|
||||
|
||||
describe "when the object is a regular one" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
o = Object.new
|
||||
def o.inspect; "a" * (VC_MAX_LENGTH + 1); end
|
||||
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<Object/
|
||||
end
|
||||
end
|
||||
|
||||
describe "when the object is a Class or a Module" do
|
||||
describe "without a name (usually a c = Class.new)" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
c, m = Class.new, Module.new
|
||||
|
||||
Pry.view_clip(c, VC_MAX_LENGTH).should =~ /#<Class/
|
||||
Pry.view_clip(m, VC_MAX_LENGTH).should =~ /#<Module/
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a #name longer than the maximum specified" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
c, m = Class.new, Module.new
|
||||
|
||||
|
||||
def c.name; "a" * (VC_MAX_LENGTH + 1); end
|
||||
def m.name; "a" * (VC_MAX_LENGTH + 1); end
|
||||
|
||||
Pry.view_clip(c, VC_MAX_LENGTH).should =~ /#<Class/
|
||||
Pry.view_clip(m, VC_MAX_LENGTH).should =~ /#<Module/
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a #name shorter than or equal to the maximum specified" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
c, m = Class.new, Module.new
|
||||
|
||||
def c.name; "a" * VC_MAX_LENGTH; end
|
||||
def m.name; "a" * VC_MAX_LENGTH; end
|
||||
|
||||
Pry.view_clip(c, VC_MAX_LENGTH).should == c.name
|
||||
Pry.view_clip(m, VC_MAX_LENGTH).should == m.name
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it 'should set the hooks default, and the default should be overridable' do
|
||||
Pry.input = InputTester.new("exit-all")
|
||||
Pry.hooks = Pry::Hooks.new.
|
||||
add_hook(:before_session, :my_name) { |out,_,_| out.puts "HELLO" }.
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "BYE" }
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output).repl
|
||||
str_output.string.should =~ /HELLO/
|
||||
str_output.string.should =~ /BYE/
|
||||
|
||||
Pry.input.rewind
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook( :before_session, :my_name) { |out,_,_| out.puts "MORNING" }.
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "EVENING" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /MORNING/
|
||||
str_output.string.should =~ /EVENING/
|
||||
|
||||
# try below with just defining one hook
|
||||
Pry.input.rewind
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook(:before_session, :my_name) { |out,_,_| out.puts "OPEN" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /OPEN/
|
||||
|
||||
Pry.input.rewind
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "CLOSE" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /CLOSE/
|
||||
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'setting custom options' do
|
||||
it 'should not raise for unrecognized options' do
|
||||
should.not.raise?(NoMethodError) {
|
||||
instance = Pry.new(:custom_option => 'custom value')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'setting custom options' do
|
||||
it 'should not raise for unrecognized options' do
|
||||
should.not.raise?(NoMethodError) {
|
||||
instance = Pry.new(:custom_option => 'custom value')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
380
test/test_pry_defaults.rb
Normal file
380
test/test_pry_defaults.rb
Normal file
|
@ -0,0 +1,380 @@
|
|||
require 'helper'
|
||||
describe "test Pry defaults" do
|
||||
|
||||
after do
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
|
||||
describe "input" do
|
||||
|
||||
after do
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
|
||||
it 'should set the input default, and the default should be overridable' do
|
||||
Pry.input = InputTester.new("5")
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.output = str_output
|
||||
Pry.new.rep
|
||||
str_output.string.should =~ /5/
|
||||
|
||||
Pry.new(:input => InputTester.new("6")).rep
|
||||
str_output.string.should =~ /6/
|
||||
end
|
||||
|
||||
it 'should pass in the prompt if readline arity is 1' do
|
||||
Pry.prompt = proc { "A" }
|
||||
|
||||
arity_one_input = Class.new do
|
||||
attr_accessor :prompt
|
||||
def readline(prompt)
|
||||
@prompt = prompt
|
||||
"exit-all"
|
||||
end
|
||||
end.new
|
||||
|
||||
Pry.start(self, :input => arity_one_input, :output => Pry::NullOutput)
|
||||
arity_one_input.prompt.should == Pry.prompt.call
|
||||
end
|
||||
|
||||
it 'should not pass in the prompt if the arity is 0' do
|
||||
Pry.prompt = proc { "A" }
|
||||
|
||||
arity_zero_input = Class.new do
|
||||
def readline
|
||||
"exit-all"
|
||||
end
|
||||
end.new
|
||||
|
||||
lambda { Pry.start(self, :input => arity_zero_input, :output => Pry::NullOutput) }.should.not.raise Exception
|
||||
end
|
||||
|
||||
it 'should not pass in the prompt if the arity is -1' do
|
||||
Pry.prompt = proc { "A" }
|
||||
|
||||
arity_multi_input = Class.new do
|
||||
attr_accessor :prompt
|
||||
|
||||
def readline(*args)
|
||||
@prompt = args.first
|
||||
"exit-all"
|
||||
end
|
||||
end.new
|
||||
|
||||
Pry.start(self, :input => arity_multi_input, :output => Pry::NullOutput)
|
||||
arity_multi_input.prompt.should == nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it 'should set the output default, and the default should be overridable' do
|
||||
Pry.input = InputTester.new("5", "6", "7")
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.output = str_output
|
||||
|
||||
Pry.new.rep
|
||||
str_output.string.should =~ /5/
|
||||
|
||||
Pry.new.rep
|
||||
str_output.string.should =~ /5\n.*6/
|
||||
|
||||
str_output2 = StringIO.new
|
||||
Pry.new(:output => str_output2).rep
|
||||
str_output2.string.should.not =~ /5\n.*6/
|
||||
str_output2.string.should =~ /7/
|
||||
end
|
||||
|
||||
it "should set the print default, and the default should be overridable" do
|
||||
new_print = proc { |out, value| out.puts value }
|
||||
Pry.print = new_print
|
||||
|
||||
Pry.new.print.should == Pry.print
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("\"test\""), :output => str_output).rep
|
||||
str_output.string.should == "test\n"
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("\"test\""), :output => str_output,
|
||||
:print => proc { |out, value| out.puts value.reverse }).rep
|
||||
str_output.string.should == "tset\n"
|
||||
|
||||
Pry.new.print.should == Pry.print
|
||||
str_output = StringIO.new
|
||||
Pry.new(:input => InputTester.new("\"test\""), :output => str_output).rep
|
||||
str_output.string.should == "test\n"
|
||||
end
|
||||
|
||||
describe "pry return values" do
|
||||
it 'should return nil' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all"), :output => Pry::NullOutput).should == nil
|
||||
end
|
||||
|
||||
it 'should return the parameter given to exit-all' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all 10"), :output => Pry::NullOutput).should == 10
|
||||
end
|
||||
|
||||
it 'should return the parameter (multi word string) given to exit-all' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all \"john mair\""), :output => Pry::NullOutput).should == "john mair"
|
||||
end
|
||||
|
||||
it 'should return the parameter (function call) given to exit-all' do
|
||||
Pry.start(self, :input => StringIO.new("exit-all 'abc'.reverse"), :output => Pry::NullOutput).should == 'cba'
|
||||
end
|
||||
|
||||
it 'should return the parameter (self) given to exit-all' do
|
||||
Pry.start("carl", :input => StringIO.new("exit-all self"), :output => Pry::NullOutput).should == "carl"
|
||||
end
|
||||
end
|
||||
|
||||
describe "prompts" do
|
||||
before do
|
||||
@empty_input_buffer = ""
|
||||
@non_empty_input_buffer = "def hello"
|
||||
@context = Pry.binding_for(0)
|
||||
end
|
||||
|
||||
it 'should set the prompt default, and the default should be overridable (single prompt)' do
|
||||
new_prompt = proc { "test prompt> " }
|
||||
Pry.prompt = new_prompt
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt> "
|
||||
|
||||
new_prompt = proc { "A" }
|
||||
pry_tester = Pry.new(:prompt => new_prompt)
|
||||
pry_tester.prompt.should == new_prompt
|
||||
pry_tester.select_prompt(@empty_input_buffer, @context).should == "A"
|
||||
pry_tester.select_prompt(@non_empty_input_buffer, @context).should == "A"
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt> "
|
||||
end
|
||||
|
||||
it 'should set the prompt default, and the default should be overridable (multi prompt)' do
|
||||
new_prompt = [proc { "test prompt> " }, proc { "test prompt* " }]
|
||||
Pry.prompt = new_prompt
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt* "
|
||||
|
||||
new_prompt = [proc { "A" }, proc { "B" }]
|
||||
pry_tester = Pry.new(:prompt => new_prompt)
|
||||
pry_tester.prompt.should == new_prompt
|
||||
pry_tester.select_prompt(@empty_input_buffer, @context).should == "A"
|
||||
pry_tester.select_prompt(@non_empty_input_buffer, @context).should == "B"
|
||||
|
||||
Pry.new.prompt.should == Pry.prompt
|
||||
Pry.new.select_prompt(@empty_input_buffer, @context).should == "test prompt> "
|
||||
Pry.new.select_prompt(@non_empty_input_buffer, @context).should == "test prompt* "
|
||||
end
|
||||
|
||||
describe 'storing and restoring the prompt' do
|
||||
before do
|
||||
make = lambda do |name,i|
|
||||
prompt = [ proc { "#{i}>" } , proc { "#{i+1}>" } ]
|
||||
(class << prompt; self; end).send(:define_method, :inspect) { "<Prompt-#{name}>" }
|
||||
prompt
|
||||
end
|
||||
@a , @b , @c = make[:a,0] , make[:b,1] , make[:c,2]
|
||||
@pry = Pry.new :prompt => @a
|
||||
end
|
||||
it 'should have a prompt stack' do
|
||||
@pry.push_prompt @b
|
||||
@pry.push_prompt @c
|
||||
@pry.prompt.should == @c
|
||||
@pry.pop_prompt
|
||||
@pry.prompt.should == @b
|
||||
@pry.pop_prompt
|
||||
@pry.prompt.should == @a
|
||||
end
|
||||
|
||||
it 'should restore overridden prompts when returning from file-mode' do
|
||||
pry = Pry.new :input => InputTester.new('shell-mode', 'shell-mode'),
|
||||
:prompt => [ proc { 'P>' } ] * 2
|
||||
pry.select_prompt(@empty_input_buffer, @context).should == "P>"
|
||||
pry.re
|
||||
pry.select_prompt(@empty_input_buffer, @context).should =~ /\Apry .* \$ \z/
|
||||
pry.re
|
||||
pry.select_prompt(@empty_input_buffer, @context).should == "P>"
|
||||
end
|
||||
|
||||
it '#pop_prompt should return the popped prompt' do
|
||||
@pry.push_prompt @b
|
||||
@pry.push_prompt @c
|
||||
@pry.pop_prompt.should == @c
|
||||
@pry.pop_prompt.should == @b
|
||||
end
|
||||
|
||||
it 'should not pop the last prompt' do
|
||||
@pry.push_prompt @b
|
||||
@pry.pop_prompt.should == @b
|
||||
@pry.pop_prompt.should == @a
|
||||
@pry.pop_prompt.should == @a
|
||||
@pry.prompt.should == @a
|
||||
end
|
||||
|
||||
describe '#prompt= should replace the current prompt with the new prompt' do
|
||||
it 'when only one prompt on the stack' do
|
||||
@pry.prompt = @b
|
||||
@pry.prompt.should == @b
|
||||
@pry.pop_prompt.should == @b
|
||||
@pry.pop_prompt.should == @b
|
||||
end
|
||||
it 'when several prompts on the stack' do
|
||||
@pry.push_prompt @b
|
||||
@pry.prompt = @c
|
||||
@pry.pop_prompt.should == @c
|
||||
@pry.pop_prompt.should == @a
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "view_clip used for displaying an object in a truncated format" do
|
||||
|
||||
VC_MAX_LENGTH = 60
|
||||
|
||||
describe "given an object with an #inspect string" do
|
||||
it "returns the #<> format of the object (never use inspect)" do
|
||||
o = Object.new
|
||||
def o.inspect; "a" * VC_MAX_LENGTH; end
|
||||
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<Object/
|
||||
end
|
||||
end
|
||||
|
||||
describe "given the 'main' object" do
|
||||
it "returns the #to_s of main (special case)" do
|
||||
o = TOPLEVEL_BINDING.eval('self')
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should == o.to_s
|
||||
end
|
||||
end
|
||||
|
||||
describe "given the a Numeric, String or Symbol object" do
|
||||
[1, 2.0, -5, "hello", :test].each do |o|
|
||||
it "returns the #inspect of the special-cased immediate object: #{o}" do
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should == o.inspect
|
||||
end
|
||||
end
|
||||
|
||||
# only testing with String here :)
|
||||
it "returns #<> format of the special-cased immediate object if #inspect is longer than maximum" do
|
||||
o = "o" * (VC_MAX_LENGTH + 1)
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<String/
|
||||
end
|
||||
end
|
||||
|
||||
describe "given an object with an #inspect string as long as the maximum specified" do
|
||||
it "returns the #<> format of the object (never use inspect)" do
|
||||
o = Object.new
|
||||
def o.inspect; "a" * VC_MAX_LENGTH; end
|
||||
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<Object/
|
||||
end
|
||||
end
|
||||
|
||||
describe "given a regular object with an #inspect string longer than the maximum specified" do
|
||||
|
||||
describe "when the object is a regular one" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
o = Object.new
|
||||
def o.inspect; "a" * (VC_MAX_LENGTH + 1); end
|
||||
|
||||
Pry.view_clip(o, VC_MAX_LENGTH).should =~ /#<Object/
|
||||
end
|
||||
end
|
||||
|
||||
describe "when the object is a Class or a Module" do
|
||||
describe "without a name (usually a c = Class.new)" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
c, m = Class.new, Module.new
|
||||
|
||||
Pry.view_clip(c, VC_MAX_LENGTH).should =~ /#<Class/
|
||||
Pry.view_clip(m, VC_MAX_LENGTH).should =~ /#<Module/
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a #name longer than the maximum specified" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
c, m = Class.new, Module.new
|
||||
|
||||
|
||||
def c.name; "a" * (VC_MAX_LENGTH + 1); end
|
||||
def m.name; "a" * (VC_MAX_LENGTH + 1); end
|
||||
|
||||
Pry.view_clip(c, VC_MAX_LENGTH).should =~ /#<Class/
|
||||
Pry.view_clip(m, VC_MAX_LENGTH).should =~ /#<Module/
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a #name shorter than or equal to the maximum specified" do
|
||||
it "returns a string of the #<class name:object idish> format" do
|
||||
c, m = Class.new, Module.new
|
||||
|
||||
def c.name; "a" * VC_MAX_LENGTH; end
|
||||
def m.name; "a" * VC_MAX_LENGTH; end
|
||||
|
||||
Pry.view_clip(c, VC_MAX_LENGTH).should == c.name
|
||||
Pry.view_clip(m, VC_MAX_LENGTH).should == m.name
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it 'should set the hooks default, and the default should be overridable' do
|
||||
Pry.input = InputTester.new("exit-all")
|
||||
Pry.hooks = Pry::Hooks.new.
|
||||
add_hook(:before_session, :my_name) { |out,_,_| out.puts "HELLO" }.
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "BYE" }
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output).repl
|
||||
str_output.string.should =~ /HELLO/
|
||||
str_output.string.should =~ /BYE/
|
||||
|
||||
Pry.input.rewind
|
||||
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook( :before_session, :my_name) { |out,_,_| out.puts "MORNING" }.
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "EVENING" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /MORNING/
|
||||
str_output.string.should =~ /EVENING/
|
||||
|
||||
# try below with just defining one hook
|
||||
Pry.input.rewind
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook(:before_session, :my_name) { |out,_,_| out.puts "OPEN" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /OPEN/
|
||||
|
||||
Pry.input.rewind
|
||||
str_output = StringIO.new
|
||||
Pry.new(:output => str_output,
|
||||
:hooks => Pry::Hooks.new.
|
||||
add_hook(:after_session, :my_name) { |out,_,_| out.puts "CLOSE" }
|
||||
).repl
|
||||
|
||||
str_output.string.should =~ /CLOSE/
|
||||
|
||||
Pry.reset_defaults
|
||||
Pry.color = false
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue