From aa03df81ca51c867e2dadbb575cba6042e2a276a Mon Sep 17 00:00:00 2001 From: John Mair Date: Wed, 22 Dec 2010 03:03:52 +1300 Subject: [PATCH] * added tests (test.rb and test_helper.rb files) * defined input/output accessors for Pry class to set global defaults for input and output (overridable by specific instances). * Added reset_defaults method to set input/output and prompt lambdas back to defaults * added output callback for 'cd' command * changed eval_string += val to eval_string << val in Pry#r method, for performance reasons (no copy made with <<) --- lib/pry.rb | 52 +++++++++++++--------- lib/pry/output.rb | 1 + test/test.rb | 103 ++++++++++++++++++++++++++++++++++++++++++++ test/test_helper.rb | 38 ++++++++++++++++ 4 files changed, 173 insertions(+), 21 deletions(-) create mode 100644 test/test.rb create mode 100644 test/test_helper.rb diff --git a/lib/pry.rb b/lib/pry.rb index d949cf3e..b8707c53 100644 --- a/lib/pry.rb +++ b/lib/pry.rb @@ -22,34 +22,48 @@ class Pry end end + def self.reset_defaults + self.input = Input.new + self.output = Output.new + + self.default_prompt = proc do |v, nest| + if nest == 0 + "pry(#{Pry.view(v)})> " + else + "pry(#{Pry.view(v)}):#{Pry.view(nest)}> " + end + end + + self.wait_prompt = proc do |v, nest| + if nest == 0 + "pry(#{Pry.view(v)})* " + else + "pry(#{Pry.view(v)}):#{Pry.view(nest)}* " + end + end + end + # class accessors class << self attr_reader :nesting attr_accessor :last_result attr_accessor :default_prompt, :wait_prompt + attr_accessor :input, :output end - self.default_prompt = proc do |v, nest| - if nest == 0 - "pry(#{Pry.view(v)})> " - else - "pry(#{Pry.view(v)}):#{Pry.view(nest)}> " - end - end - - self.wait_prompt = proc do |v, nest| - if nest == 0 - "pry(#{Pry.view(v)})* " - else - "pry(#{Pry.view(v)}):#{Pry.view(nest)}* " - end + self.reset_defaults + + @nesting = [] + + def @nesting.level + last.is_a?(Array) ? last.first : nil end attr_accessor :input, :output attr_accessor :default_prompt, :wait_prompt attr_reader :last_result - def initialize(input = Input.new, output = Output.new) + def initialize(input = Pry.input, output = Pry.output) @input = input @output = output @@ -57,11 +71,6 @@ class Pry @wait_prompt = Pry.wait_prompt end - @nesting = [] - - def @nesting.level - last.is_a?(Array) ? last.first : nil - end def nesting self.class.nesting @@ -123,7 +132,7 @@ class Pry eval_string = "" loop do val = input.read(prompt(eval_string, target, nesting.level)) - eval_string += "#{val.chomp}\n" + eval_string << "#{val.chomp}\n" process_commands(val, eval_string, target) break eval_string if valid_expression?(eval_string) @@ -163,6 +172,7 @@ class Pry eval_string.clear when /^cd\s+(.+)/ obj = $~.captures.first + output.cd(obj) target.eval("#{obj}.pry") eval_string.clear when /^show_doc\s*(.+)/ diff --git a/lib/pry/output.rb b/lib/pry/output.rb index d083e443..b117f782 100644 --- a/lib/pry/output.rb +++ b/lib/pry/output.rb @@ -94,6 +94,7 @@ class Pry end def exit() end + def cd(*) end def jump_to(nesting_level_breakout) end def exit_program() end end diff --git a/test/test.rb b/test/test.rb new file mode 100644 index 00000000..1e1a70b7 --- /dev/null +++ b/test/test.rb @@ -0,0 +1,103 @@ +direc = File.dirname(__FILE__) + +require 'bacon' +require "#{direc}/../lib/pry" +require "#{direc}/test_helper" + +describe Pry do + describe "open a Pry session on an object" do + describe "rep" do + it 'should set an ivar on an object' do + input_string = "@x = 10" + input = InputTester.new(input_string) + output = OutputTester.new + o = Object.new + + pry_tester = Pry.new(input, output) + pry_tester.rep(o) + o.instance_variable_get(:@x).should == 10 + end + + it 'should make self evaluate to the receiver of the rep session' do + output = OutputTester.new + o = Object.new + + pry_tester = Pry.new(InputTester.new("self"), output) + pry_tester.rep(o) + output.output_buffer.should == o + end + end + + describe "repl" do + describe "commands" do + + before do + Pry.input = InputTester.new("exit") + Pry.output = OutputTester.new + end + + after do + Pry.reset_defaults + end + + { "!" => "refresh", + "help" => "show_help", + "nesting" => "show_nesting", + "status" => "show_status", + "cat dummy" => "cat", + "cd 3" => "cd", + "ls" => "ls", + "show_method test_method" => "show_method", + "show_imethod test_method" => "show_method", + "show_doc test_method" => "show_doc", + "show_idoc test_method" => "show_doc", + "jump_to 0" => "jump_to" + }.each do |command, meth| + + eval %{ + it "should invoke output##{meth} when #{command} command entered" do + input_strings = ["#{command}", "exit"] + input = InputTester.new(input_strings) + output = OutputTester.new + o = Class.new + + pry_tester = Pry.new(input, output) + pry_tester.repl(o) + + output.#{meth}_invoked.should == true + output.session_end_invoked.should == true + end + } + + + # it "should invoke output#help when help command entered" do + # input_strings = ["help", "exit"] + # input = InputTester.new(input_strings) + # output = OutputTester.new + # o = Object.new + + # pry_tester = Pry.new(input, output) + # pry_tester.repl(o) + + # output.show_help_invoked.should == true + # output.session_end_invoked.should == true + # end + + # it 'should set an ivar on an object and exit the repl' do + # input_strings = ["@x = 10", "exit"] + # input = InputTester.new(input_strings) + # output = OutputTester.new + + # o = Object.new + + # pry_tester = Pry.new(input, output) + # pry_tester.repl(o) + + # o.instance_variable_get(:@x).should == 10 + # output.session_end_invoked.should == true + # end + end + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 00000000..ec8c96a4 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,38 @@ +class Object + def test_method + end +end + +class InputTester + def initialize(actions) + @orig_actions = Array(actions.dup) + @actions = Array(actions) + end + + def read(*) + @actions.shift + end + + def rewind + @actions = @orig_actions + end +end + +class OutputTester + attr_reader :output_buffer + + def initialize + @output_buffer = "" + end + + def print(val) + @output_buffer = val + puts val.inspect + end + + def method_missing(meth_name, *args, &block) + define_singleton_method("#{meth_name}_invoked") { true } + end +end + +