[macruby-changes] [4317] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sun Jul 4 05:32:30 PDT 2010
Revision: 4317
http://trac.macosforge.org/projects/ruby/changeset/4317
Author: eloy.de.enige at gmail.com
Date: 2010-07-04 05:32:27 -0700 (Sun, 04 Jul 2010)
Log Message:
-----------
Update DietRB to 75ec79, which includes the specs: $ rake spec:irb
Modified Paths:
--------------
MacRuby/trunk/lib/irb/formatter.rb
MacRuby/trunk/rakelib/spec.rake
MacRuby/trunk/spec/macruby.mspec
Added Paths:
-----------
MacRuby/trunk/spec/dietrb/
MacRuby/trunk/spec/dietrb/context_spec.rb
MacRuby/trunk/spec/dietrb/ext/
MacRuby/trunk/spec/dietrb/ext/colorize_spec.rb
MacRuby/trunk/spec/dietrb/ext/completion_spec.rb
MacRuby/trunk/spec/dietrb/ext/history_spec.rb
MacRuby/trunk/spec/dietrb/formatter_spec.rb
MacRuby/trunk/spec/dietrb/regression/
MacRuby/trunk/spec/dietrb/regression/context_spec.rb
MacRuby/trunk/spec/dietrb/source_spec.rb
MacRuby/trunk/spec/dietrb/spec_helper.rb
Modified: MacRuby/trunk/lib/irb/formatter.rb
===================================================================
--- MacRuby/trunk/lib/irb/formatter.rb 2010-07-02 13:13:23 UTC (rev 4316)
+++ MacRuby/trunk/lib/irb/formatter.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -38,7 +38,9 @@
def inspect_object(object)
if @inspect
- object.respond_to?(:pretty_inspect) ? object.pretty_inspect : object.inspect
+ result = object.respond_to?(:pretty_inspect) ? object.pretty_inspect : object.inspect
+ result.strip!
+ result
else
address = object.__id__ * 2
address += 0x100000000 if address < 0
Modified: MacRuby/trunk/rakelib/spec.rake
===================================================================
--- MacRuby/trunk/rakelib/spec.rake 2010-07-02 13:13:23 UTC (rev 4316)
+++ MacRuby/trunk/rakelib/spec.rake 2010-07-04 12:32:27 UTC (rev 4317)
@@ -44,6 +44,11 @@
mspec :ci, ":library"
end
+ desc "Run the DietRB specs"
+ task :irb do
+ mspec :ci, "./spec/dietrb"
+ end
+
desc "Run language examples that are known to fail"
task :fails do
mspec :run, "-g fails :full"
Added: MacRuby/trunk/spec/dietrb/context_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/context_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/context_spec.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,244 @@
+require File.expand_path('../spec_helper', __FILE__)
+require 'tempfile'
+
+def stub_Readline
+ class << Readline
+ attr_reader :received
+
+ def stub_input(*input)
+ @input = input
+ end
+
+ def readline(prompt, history)
+ @received = [prompt, history]
+ @input.shift
+ end
+ end
+end
+stub_Readline
+
+class TestProcessor
+ def input(s)
+ s * 2
+ end
+end
+
+main = self
+
+describe "IRB::Context" do
+ before do
+ @context = IRB::Context.new(main)
+ end
+
+ it "initializes with an object and stores a copy of its binding" do
+ @context.object.should == main
+ eval("self", @context.binding).should == main
+ eval("x = :ok", @context.binding)
+ eval("y = x", @context.binding)
+ eval("y", @context.binding).should == :ok
+ end
+
+ it "initializes with an object and an explicit binding" do
+ context = IRB::Context.new(Object.new, TOPLEVEL_BINDING)
+ eval("class InTopLevel; end", context.binding)
+ lambda { ::InTopLevel }.should_not raise_error(NameError)
+ end
+
+ it "initializes with an 'empty' state" do
+ @context.line.should == 1
+ @context.source.class.should == IRB::Source
+ @context.source.to_s.should == ""
+ end
+
+ it "initializes with an instance of each processor" do
+ before = IRB::Context.processors.dup
+ begin
+ IRB::Context.processors << TestProcessor
+ @context = IRB::Context.new(main)
+ @context.processors.last.class.should == TestProcessor
+ ensure
+ IRB::Context.processors.replace(before)
+ end
+ end
+
+ it "does not use the same binding copy of the top level object" do
+ lambda { eval("x", @context.binding) }.should raise_error(NameError)
+ end
+
+ it "makes itself the current running context during the runloop and resigns once it's done" do
+ IRB::Context.current.should == nil
+
+ Readline.stub_input("current_during_run = IRB::Context.current")
+ @context.run
+ eval('current_during_run', @context.binding).should == @context
+
+ IRB::Context.current.should == nil
+ end
+end
+
+describe "IRB::Context, when evaluating source" do
+ before do
+ @context = IRB::Context.new(main)
+ def @context.printed; @printed ||= '' end
+ def @context.puts(string); printed << "#{string}\n" end
+ IRB.formatter = IRB::Formatter.new
+ end
+
+ it "evaluates code with the object's binding" do
+ @context.__evaluate__("self").should == main
+ end
+
+ it "prints the result" do
+ @context.evaluate("Hash[:foo, :foo]")
+ @context.printed.should == "=> {:foo=>:foo}\n"
+ end
+
+ it "assigns the result to the local variable `_'" do
+ result = @context.evaluate("Object.new")
+ @context.evaluate("_").should == result
+ @context.evaluate("_").should == result
+ end
+
+ it "coerces the given source to a string first" do
+ o = Object.new
+ def o.to_s; "self"; end
+ @context.evaluate(o).should == main
+ end
+
+ it "rescues any type of exception" do
+ lambda {
+ @context.evaluate("DoesNotExist")
+ @context.evaluate("raise Exception")
+ }.should_not.raise_error
+ end
+
+ it "assigns the last raised exception to the global variable `$EXCEPTION' / `$e'" do
+ @context.evaluate("DoesNotExist")
+ $EXCEPTION.class.should == NameError
+ $EXCEPTION.message.should include('DoesNotExist')
+ $e.should == $EXCEPTION
+ end
+
+ it "prints the exception that occurs" do
+ @context.evaluate("DoesNotExist")
+ @context.printed.should =~ /^NameError:.+DoesNotExist/
+ end
+
+ it "uses the line number of the *first* line in the buffer, for the line parameter of eval" do
+ @context.process_line("DoesNotExist")
+ @context.printed.should =~ /\(irb\):1:in/
+ @context.process_line("class A")
+ @context.process_line("DoesNotExist")
+ @context.process_line("end")
+ @context.printed.should =~ /\(irb\):3:in.+\(irb\):2:in/m
+ end
+
+ it "inputs a line to be processed, skipping readline" do
+ expected = "#{@context.formatter.prompt(@context)}2 * 21\n=> 42\n"
+ @context.input_line("2 * 21")
+ @context.printed.should == expected
+ end
+end
+
+describe "IRB::Context, when receiving input" do
+ before do
+ @context = IRB::Context.new(main)
+ end
+
+ it "prints the prompt, reads a line, saves it to the history and returns it" do
+ Readline.stub_input("def foo")
+ @context.readline.should == "def foo"
+ Readline.received.should == ["irb(main):001:0> ", true]
+ end
+
+ it "passes the input to all processors, which may return a new value" do
+ @context.processors << TestProcessor.new
+ Readline.stub_input("foo")
+ @context.readline.should == "foofoo"
+ end
+
+ it "processes the output" do
+ Readline.stub_input("def foo")
+ def @context.process_line(line); @received = line; false; end
+ @context.run
+ @context.instance_variable_get(:@received).should == "def foo"
+ end
+
+ it "adds the received code to the source buffer" do
+ @context.process_line("def foo")
+ @context.process_line("p :ok")
+ @context.source.to_s.should == "def foo\np :ok"
+ end
+
+ it "clears the source buffer when an Interrupt signal is received" do
+ begin
+ @context.process_line("def foo")
+
+ def Readline.readline(*args)
+ unless @raised
+ @raised = true
+ raise Interrupt
+ end
+ end
+
+ lambda { @context.run }.should_not raise_error(Interrupt)
+ @context.source.to_s.should == ""
+ ensure
+ stub_Readline
+ end
+ end
+
+ it "increases the current line number" do
+ @context.line.should == 1
+ @context.process_line("def foo")
+ @context.line.should == 2
+ @context.process_line("p :ok")
+ @context.line.should == 3
+ end
+
+ it "evaluates the buffered source once it's a valid code block" do
+ def @context.evaluate(source); @evaled = source; end
+
+ @context.process_line("def foo")
+ @context.process_line(":ok")
+ @context.process_line("end; p foo")
+
+ source = @context.instance_variable_get(:@evaled)
+ source.to_s.should == "def foo\n:ok\nend; p foo"
+ end
+
+ it "prints that a syntax error occurred on the last line and reset the buffer to the previous line" do
+ def @context.puts(str); @printed = str; end
+
+ @context.process_line("def foo")
+ @context.process_line(" };")
+
+ @context.source.to_s.should == "def foo"
+ printed = @context.instance_variable_get(:@printed)
+ printed.should == "SyntaxError: compile error\n(irb):2: syntax error, unexpected '}'"
+ end
+
+ it "returns whether or not the runloop should continue, but only if the level is 0" do
+ @context.process_line("def foo").should == true
+ @context.process_line("quit").should == true
+ @context.process_line("end").should == true
+
+ @context.process_line("quit").should == false
+ end
+
+ it "exits the runloop if the user wishes so" do
+ Readline.stub_input("quit", "def foo")
+ def @context.process_line(line); @received = line; super; end
+ @context.run
+ @context.instance_variable_get(:@received).should_not == "def foo"
+ end
+end
+
+describe "Kernel::irb" do
+ it "creates a new context for the given object and runs it" do
+ Readline.stub_input("::IRBRan = self")
+ o = Object.new
+ irb(o)
+ IRBRan.should == o
+ end
+end
Added: MacRuby/trunk/spec/dietrb/ext/colorize_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/ext/colorize_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/ext/colorize_spec.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,58 @@
+require File.expand_path('../../spec_helper', __FILE__)
+require 'irb/ext/colorize'
+
+main = self
+
+describe "IRB::ColoredFormatter" do
+ before do
+ @formatter = IRB::ColoredFormatter.new
+ @context = IRB::Context.new(main)
+ end
+
+ it "colorizes a constant" do
+ @formatter.result(Hash).should == "=> \e[1;32mHash\e[0;0m"
+ end
+
+ it "colorizes a numeric" do
+ @formatter.result(1).should == "=> \e[0;36m1\e[0;0m"
+ @formatter.result(1.2).should == "=> \e[0;36m1.2\e[0;0m"
+ end
+
+ # Not Wirble compliant
+ it "colorizes a Range" do
+ # @formatter.result(1..3).should == "=> \e[0;36m1\e[0;0m\e[0;31m..\e[0;0m\e[0;36m3\e[0;0m"
+ @formatter.result(1..3).should == "=> \e[0;36m1\e[0;0m\e[0;34m..\e[0;0m\e[0;36m3\e[0;0m"
+ end
+
+ it "colorizes a String" do
+ @formatter.result("foo bar").should == "=> \e[0;31m\"\e[0;0m\e[0;36mfoo bar\e[0;0m\e[0;31m\"\e[0;0m"
+ end
+
+ it "colorizes a Hash" do
+ @formatter.result(:ok => :foo).should == "=> \e[0;32m{\e[0;0m\e[1;33m:\e[0;0m\e[1;33mok\e[0;0m\e[0;34m=>\e[0;0m\e[1;33m:\e[0;0m\e[1;33mfoo\e[0;0m\e[0;32m}\e[0;0m"
+ end
+
+ it "colorizes an Array" do
+ @formatter.result([1, 2]).should == "=> \e[0;32m[\e[0;0m\e[0;36m1\e[0;0m\e[0;34m,\e[0;0m \e[0;36m2\e[0;0m\e[0;32m]\e[0;0m"
+ end
+
+ it "colorizes the prompt" do
+ @formatter.colors[:prompt] = :light_green
+ @formatter.prompt(@context).should == "\e[1;32m#{IRB::Formatter.new.prompt(@context)}\e[0;0m"
+ end
+
+ it "colorizes the result prefix" do
+ @formatter.colors[:result_prefix] = :light_red
+ @formatter.result("").should == "\e[1;31m=>\e[0;0m \e[0;31m\"\e[0;0m\e[0;31m\"\e[0;0m"
+ end
+
+ it "uses the dark_background color scheme by default" do
+ @formatter.color_scheme.should == :dark_background
+ end
+
+ it "changes color scheme" do
+ @formatter.color_scheme = :fresh
+ @formatter.color_scheme.should == :fresh
+ @formatter.colors[:result_prefix].should == :light_purple
+ end
+end
\ No newline at end of file
Added: MacRuby/trunk/spec/dietrb/ext/completion_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/ext/completion_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/ext/completion_spec.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,237 @@
+require File.expand_path('../../spec_helper', __FILE__)
+require 'irb/ext/completion'
+
+module CompletionHelper
+ def complete(str)
+ IRB::Completion.new(@context, str).results
+ end
+
+ def imethods(klass, receiver = nil)
+ klass.instance_methods.map { |m| [receiver, m.to_s].compact.join('.') }.sort
+ end
+
+ def methods(object, receiver = nil)
+ object.methods.map { |m| [receiver, m.to_s].compact.join('.') }.sort
+ end
+end
+
+class CompletionStub
+ def self.a_cmethod
+ end
+
+ def an_imethod
+ end
+end
+
+class Playground
+ CompletionStub = Object.new
+ def CompletionStub.a_singleton_method; end
+
+ def a_local_method; end
+end
+
+$a_completion_stub = CompletionStub.new
+
+describe "IRB::Completion" do
+ extend CompletionHelper
+
+ before do
+ @context = IRB::Context.new(Playground.new)
+ end
+
+ it "quacks like a Proc" do
+ IRB::Completion.call('//.').should == imethods(Regexp, '//')
+ end
+
+ describe "when doing a method call on an explicit receiver," do
+ describe "and the source ends with a period," do
+ describe "returns *all* public methods of the receiver that" do
+ it "matches as a local variable" do
+ @context.__evaluate__('foo = ::CompletionStub.new')
+ complete('foo.').should == imethods(::CompletionStub, 'foo')
+
+ @context.__evaluate__('def foo.singleton_method; end')
+ complete('foo.').should include('foo.singleton_method')
+ end
+
+ it "matches as a global variable" do
+ complete('$a_completion_stub.').should == imethods(::CompletionStub, '$a_completion_stub')
+ end
+
+ # TODO: fix
+ # it "matches as a local constant" do
+ # complete('CompletionStub.').should == methods(Playground::CompletionStub)
+ # end
+
+ it "matches as a top level constant" do
+ complete('::CompletionStub.').should == methods(::CompletionStub, '::CompletionStub')
+ end
+ end
+
+ describe "returns *all* public instance methods of the class (the receiver) that" do
+ it "matches as a Regexp literal" do
+ complete('//.').should == imethods(Regexp, '//')
+ complete('/^(:[^:.]+)\.([^.]*)$/.').should == imethods(Regexp, '/^(:[^:.]+)\.([^.]*)$/')
+ complete('/^(#{oops})\.([^.]*)$/.').should == imethods(Regexp, '/^(#{oops})\.([^.]*)$/')
+ complete('%r{/foo/.*/bar}.').should == imethods(Regexp, '%r{/foo/.*/bar}')
+ end
+
+ it "matches as an Array literal" do
+ complete('[].').should == imethods(Array, '[]')
+ complete('[:ok, {}, "foo",].').should == imethods(Array, '[:ok, {}, "foo",]')
+ complete('[*foo].').should == imethods(Array, '[*foo]')
+ complete('%w{foo}.').should == imethods(Array, '%w{foo}')
+ complete('%W{#{:foo}}.').should == imethods(Array, '%W{#{:foo}}')
+ end
+
+ # fails on MacRuby
+ it "matches as a lambda literal" do
+ complete('->{}.').should == imethods(Proc, '->{}')
+ complete('->{x=:ok}.').should == imethods(Proc, '->{x=:ok}')
+ complete('->(x){x=:ok}.').should == imethods(Proc, '->(x){x=:ok}')
+ end
+
+ it "matches as a Hash literal" do
+ complete('{}.').should == imethods(Hash, '{}')
+ complete('{:foo=>:bar,}.').should == imethods(Hash, '{:foo=>:bar,}')
+ complete('{foo:"bar"}.').should == imethods(Hash, '{foo:"bar"}')
+ end
+
+ it "matches as a Symbol literal" do
+ complete(':foo.').should == imethods(Symbol, ':foo')
+ complete(':"foo.bar".').should == imethods(Symbol, ':"foo.bar"')
+ complete(':"foo.#{"bar"}".').should == imethods(Symbol, ':"foo.#{"bar"}"')
+ complete(':\'foo.#{"bar"}\'.').should == imethods(Symbol, ':\'foo.#{"bar"}\'')
+ complete('%s{foo.bar}.').should == imethods(Symbol, '%s{foo.bar}')
+ end
+
+ it "matches as a String literal" do
+ complete("'foo\\'bar'.").should == imethods(String, "'foo\\'bar'")
+ complete('"foo\"bar".').should == imethods(String, '"foo\"bar"')
+ complete('"foo#{"bar"}".').should == imethods(String, '"foo#{"bar"}"')
+ complete('%{foobar}.').should == imethods(String, '%{foobar}')
+ complete('%q{foo#{:bar}}.').should == imethods(String, '%q{foo#{:bar}}')
+ complete('%Q{foo#{:bar}}.').should == imethods(String, '%Q{foo#{:bar}}')
+ end
+
+ it "matches as a Range literal" do
+ complete('1..10.').should == imethods(Range, '1..10')
+ complete('1...10.').should == imethods(Range, '1...10')
+ complete('"a".."z".').should == imethods(Range, '"a".."z"')
+ complete('"a"..."z".').should == imethods(Range, '"a"..."z"')
+ end
+
+ it "matches as a Fixnum literal" do
+ complete('42.').should == imethods(Fixnum, '42')
+ complete('+42.').should == imethods(Fixnum, '+42')
+ complete('-42.').should == imethods(Fixnum, '-42')
+ complete('42_000.').should == imethods(Fixnum, '42_000')
+ end
+
+ it "matches as a Bignum literal as a Fixnum" do
+ complete('100_000_000_000_000_000_000.').should == imethods(Fixnum, '100_000_000_000_000_000_000')
+ complete('-100_000_000_000_000_000_000.').should == imethods(Fixnum, '-100_000_000_000_000_000_000')
+ complete('+100_000_000_000_000_000_000.').should == imethods(Fixnum, '+100_000_000_000_000_000_000')
+ end
+
+ it "matches as a Float with exponential literal" do
+ complete('1.2e-3.').should == imethods(Float, '1.2e-3')
+ complete('+1.2e-3.').should == imethods(Float, '+1.2e-3')
+ complete('-1.2e-3.').should == imethods(Float, '-1.2e-3')
+ end
+
+ it "matches as a hex literal as a Fixnum" do
+ complete('0xffff.').should == imethods(Fixnum, '0xffff')
+ complete('+0xffff.').should == imethods(Fixnum, '+0xffff')
+ complete('-0xffff.').should == imethods(Fixnum, '-0xffff')
+ end
+
+ it "matches as a binary literal as a Fixnum" do
+ complete('0b01011.').should == imethods(Fixnum, '0b01011')
+ complete('-0b01011.').should == imethods(Fixnum, '-0b01011')
+ complete('+0b01011.').should == imethods(Fixnum, '+0b01011')
+ end
+
+ it "matches as an octal literal as a Fixnum" do
+ complete('0377.').should == imethods(Fixnum, '0377')
+ complete('-0377.').should == imethods(Fixnum, '-0377')
+ complete('+0377.').should == imethods(Fixnum, '+0377')
+ end
+
+ it "matches as a Float literal" do
+ complete('42.0.').should == imethods(Float, '42.0')
+ complete('-42.0.').should == imethods(Float, '-42.0')
+ complete('+42.0.').should == imethods(Float, '+42.0')
+ complete('42_000.0.').should == imethods(Float, '42_000.0')
+ end
+
+ it "matches as a Bignum float literal as a Float" do
+ complete('100_000_000_000_000_000_000.0.').should == imethods(Float, '100_000_000_000_000_000_000.0')
+ complete('+100_000_000_000_000_000_000.0.').should == imethods(Float, '+100_000_000_000_000_000_000.0')
+ complete('-100_000_000_000_000_000_000.0.').should == imethods(Float, '-100_000_000_000_000_000_000.0')
+ end
+ end
+
+ it "returns *all* public instance methods of the class (the receiver) that ::new is called on" do
+ complete("Playground.new.").should == imethods(Playground, 'Playground.new')
+ complete("Playground.new.a_local_m").should == %w{ Playground.new.a_local_method }
+
+ @context.__evaluate__("klass = Playground")
+ complete("klass.new.").should == imethods(Playground, 'klass.new')
+ complete("klass.new.a_local_m").should == %w{ klass.new.a_local_method }
+ end
+ end
+
+ describe "and the source does *not* end with a period," do
+ it "filters the methods, of the literal receiver, by the given method name" do
+ complete('//.nam').should == %w{ //.named_captures //.names }
+ complete('//.named').should == %w{ //.named_captures }
+ end
+
+ it "filters the methods, of the variable receiver, by the given method name" do
+ @context.__evaluate__('foo = ::CompletionStub.new')
+ complete('foo.an_im').should == %w{ foo.an_imethod }
+ complete('$a_completion_stub.an_im').should == %w{ $a_completion_stub.an_imethod }
+ # TODO: fix
+ # complete('CompletionStub.a_sing').should == %w{ CompletionStub.a_singleton_method }
+ end
+ end
+ end
+
+ describe "when *not* doing a method call on an explicit receiver" do
+ before do
+ @context.__evaluate__("a_local_variable = :ok")
+ end
+
+ it "matches local variables" do
+ complete("a_local_v").should == %w{ a_local_variable }
+ end
+
+ it "matches instance methods of the context object" do
+ complete("a_local_m").should == %w{ a_local_method }
+ end
+
+ it "matches local variables and instance method of the context object" do
+ complete("a_loc").should == %w{ a_local_method a_local_variable }
+ end
+
+ it "matches global variables" do
+ complete("$a_completion_s").should == %w{ $a_completion_stub }
+ end
+
+ it "matches constants" do
+ complete("Playgr").should == %w{ Playground }
+ end
+
+ it "matches top level constants" do
+ complete("::CompletionSt").should == %w{ ::CompletionStub }
+ end
+ end
+
+ it "completes reserved words as variables or constants" do
+ (IRB::Completion::RESERVED_DOWNCASE_WORDS +
+ IRB::Completion::RESERVED_UPCASE_WORDS).each do |word|
+ complete(word[0..-2]).should include(word)
+ end
+ end
+end
\ No newline at end of file
Added: MacRuby/trunk/spec/dietrb/ext/history_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/ext/history_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/ext/history_spec.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,187 @@
+require File.expand_path('../../spec_helper', __FILE__)
+require "tempfile"
+
+describe "IRB::History, by default," do
+ it "stores the history in ~/.irb_history" do
+ IRB::History.file.should == File.expand_path("~/.irb_history")
+ end
+end
+
+describe "IRB::History" do
+ before do
+ @file = Tempfile.new("irb_history.txt")
+ IRB::History.file = @file.path
+ @history = IRB::History.new(nil)
+ end
+
+ after do
+ @file.close
+ end
+
+ it "adds input to the history file" do
+ @history.input "puts :ok"
+ @file.rewind; @file.read.should == "puts :ok\n"
+ @history.input "foo(x)"
+ @file.rewind; @file.read.should == "puts :ok\nfoo(x)\n"
+ end
+
+ it "returns the same input value" do
+ @history.input("foo(x)").should == "foo(x)"
+ end
+
+ it "returns the contents of the history file as an array of lines" do
+ @history.input "puts :ok"
+ @history.to_a.should == ["puts :ok"]
+ @history.input "foo(x)"
+ @history.to_a.should == ["puts :ok", "foo(x)"]
+ end
+
+ it "returns an empty array if the history file doesn't exist yet and create it once input is added" do
+ @file.close
+ FileUtils.rm(@file.path)
+
+ @history.to_a.should == []
+ File.exist?(@file.path).should == false
+
+ @history.input "puts :ok"
+ File.exist?(@file.path).should == true
+ @history.to_a.should == ["puts :ok"]
+ end
+
+ it "stores the contents of the history file in Readline::HISTORY once" do
+ Readline::HISTORY.clear
+
+ @history.input "puts :ok"
+ @history.input "foo(x)"
+
+ IRB::History.new(nil)
+ IRB::History.new(nil)
+
+ Readline::HISTORY.to_a.should == ["puts :ok", "foo(x)"]
+ end
+
+ it "clears the history and history file" do
+ @history.input "puts :ok"
+ @history.input "foo(x)"
+ @history.clear!
+
+ @file.rewind; @file.read.should == ""
+ Readline::HISTORY.to_a.should == []
+ end
+end
+
+class IRB::History
+ def printed
+ @printed ||= ""
+ end
+
+ def print(s)
+ printed << s
+ end
+
+ def puts(s)
+ printed << "#{s}\n"
+ end
+
+ def clear!
+ @cleared = true
+ end
+ def cleared?
+ @cleared
+ end
+end
+
+describe "IRB::History, concerning the user api, by default," do
+ it "shows a maximum of 50 history entries" do
+ IRB::History.max_entries_in_overview.should == 50
+ end
+end
+
+describe "IRB::History, concerning the user api," do
+ before do
+ sources = [
+ "puts :ok",
+ "x = foo(x)",
+ "class AAA",
+ " def bar",
+ " :ok",
+ " end",
+ "end",
+ "THIS LINE REPRESENTS THE ENTERED COMMAND AND SHOULD BE OMITTED!"
+ ]
+
+ Readline::HISTORY.clear
+ sources.each { |source| Readline::HISTORY.push(source) }
+
+ IRB::History.max_entries_in_overview = 5
+
+ @context = IRB::Context.new(Object.new)
+ IRB::Context.current = @context
+
+ @history = @context.processors.find { |p| p.is_a?(IRB::History) }
+ end
+
+ after do
+ IRB::Context.current = nil
+ end
+
+ it "returns nil so that IRB doesn't cache some arbitrary line number" do
+ history.should == nil
+ end
+
+ it "prints a formatted list with, by default IRB::History.max_entries_in_overview, number of history entries" do
+ history
+
+ @history.printed.should == %{
+2: class AAA
+3: def bar
+4: :ok
+5: end
+6: end
+}.sub(/\n/, '')
+ end
+
+ it "prints a formatted list of N most recent history entries" do
+ history(7)
+
+ @history.printed.should == %{
+0: puts :ok
+1: x = foo(x)
+2: class AAA
+3: def bar
+4: :ok
+5: end
+6: end
+}.sub(/\n/, '')
+ end
+
+ it "prints a formatted list of all history entries if the request number of entries is more than there is" do
+ history(777)
+
+ @history.printed.should == %{
+0: puts :ok
+1: x = foo(x)
+2: class AAA
+3: def bar
+4: :ok
+5: end
+6: end
+}.sub(/\n/, '')
+ end
+
+ it "evaluates the history entry specified" do
+ @context.__evaluate__("x = 2; def foo(x); x * 2; end")
+ history! 1
+ @context.__evaluate__("x").should == 4
+ end
+
+ it "evaluates the history entries specified by a range" do
+ history! 2..6
+ @context.__evaluate__("AAA.new.bar").should == :ok
+ end
+
+ it "clears the history and history file" do
+ clear_history!
+ @history.cleared?.should == true
+ end
+end
\ No newline at end of file
Added: MacRuby/trunk/spec/dietrb/formatter_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/formatter_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/formatter_spec.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,78 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+main = self
+
+describe "IRB::Formatter" do
+ before do
+ @formatter = IRB::Formatter.new
+ @context = IRB::Context.new(main)
+ end
+
+ it "returns a prompt string, displaying line number and code indentation level" do
+ @formatter.prompt(@context).should == "irb(main):001:0> "
+ @context.instance_variable_set(:@line, 23)
+ @formatter.prompt(@context).should == "irb(main):023:0> "
+ @context.source << "def foo"
+ @formatter.prompt(@context).should == "irb(main):023:1> "
+ end
+
+ it "describes the context's object in the prompt" do
+ o = Object.new
+ @formatter.prompt(IRB::Context.new(o)).should == "irb(#{o.inspect}):001:0> "
+ end
+
+ it "returns a very simple prompt if specified" do
+ @formatter.prompt = :simple
+ @formatter.prompt(@context).should == ">> "
+ end
+
+ it "returns no prompt if specified" do
+ @formatter.prompt = nil
+ @formatter.prompt(@context).should == ""
+ end
+
+ it "returns a formatted exception message, with the lines, regarding dietrb, filtered out of the backtrace" do
+ begin; @context.__evaluate__('DoesNotExist'); rescue NameError => e; exception = e; end
+ backtrace = exception.backtrace.reject { |f| f =~ /#{ROOT}/ }
+ @formatter.exception(exception).should ==
+ "NameError: uninitialized constant IRB::Context::DoesNotExist\n\t#{backtrace.join("\n\t")}"
+ end
+
+ it "does not filter the backtrace if $DEBUG is true" do
+ begin
+ before, $DEBUG = $DEBUG, true
+
+ begin; @context.__evaluate__('DoesNotExist'); rescue NameError => e; exception = e; end
+ @formatter.exception(exception).should ==
+ "NameError: uninitialized constant IRB::Context::DoesNotExist\n\t#{exception.backtrace.join("\n\t")}"
+ ensure
+ $DEBUG = before
+ end
+ end
+
+ it "prints the result" do
+ @formatter.result(:foo => :foo).should == "=> {:foo=>:foo}"
+ end
+
+ it "prints the result with object#pretty_inspect, if it responds to it" do
+ object = Object.new
+ def object.pretty_inspect; "foo"; end
+ @formatter.result(object).should == "=> foo"
+ end
+
+ it "prints only the class name and memory address in `no inspect' mode" do
+ @formatter.inspect = false
+
+ object = Object.new
+ def object.inspect; @inspected = true; "Never called!"; end
+ def object.__id__; 2158110700; end
+
+ @formatter.result(object).should == "=> #<Object:0x101444fd8>"
+ object.instance_variable_get(:@inspected).should_not == true
+ end
+
+ it "prints that a syntax error occurred on the last line and reset the buffer to the previous line" do
+ @formatter.syntax_error(2, "syntax error, unexpected '}'").should ==
+ "SyntaxError: compile error\n(irb):2: syntax error, unexpected '}'"
+ end
+end
\ No newline at end of file
Added: MacRuby/trunk/spec/dietrb/regression/context_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/regression/context_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/regression/context_spec.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,16 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+main = self
+
+describe "IRB::Context, when evaluating source" do
+ before do
+ @context = IRB::Context.new(main)
+ def @context.printed; @printed ||= '' end
+ def @context.puts(string); printed << "#{string}\n" end
+ end
+
+ it "does not assign the result to the `_' variable in one go, so it doesn't show up in a syntax error" do
+ @context.evaluate("'banana;")
+ @context.printed.should_not include("_ = ('banana;)")
+ end
+end
\ No newline at end of file
Added: MacRuby/trunk/spec/dietrb/source_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/source_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/source_spec.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,196 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+describe "IRB::Source" do
+ before do
+ @source = IRB::Source.new
+ end
+
+ it "initializes with an empty buffer" do
+ @source.buffer.should == []
+ end
+
+ it "appends source to the buffer, removing trailing newlines" do
+ @source << "foo\n"
+ @source << "bar\r\n"
+ @source.buffer.should == %w{ foo bar }
+ end
+
+ it "ignores empty strings" do
+ @source << ""
+ @source << " \n"
+ @source.buffer.should == []
+ end
+
+ it "removes the last line from the buffer" do
+ @source << "foo\n"
+ @source << "bar\r\n"
+ @source.pop.should == "bar"
+ @source.buffer.should == %w{ foo }
+ end
+
+ it "returns the full buffered source, joined by newlines" do
+ @source.source.should == ""
+ @source << "foo\n"
+ @source.source.should == "foo"
+ @source << "bar\r\n"
+ @source.source.should == "foo\nbar"
+ end
+
+ it "aliases #to_s to #source" do
+ @source << "foo"
+ @source << "bar"
+ @source.to_s.should == "foo\nbar"
+ end
+
+ it "returns that the accumulated source is a valid code block" do
+ [
+ ["def foo", "p :ok", "end"],
+ ["class A; def", "foo(x); p x", "end; end"]
+ ].each do |buffer|
+ IRB::Source.new(buffer).code_block?.should == true
+ end
+ end
+
+ it "returns that the accumulated source is not a valid code block" do
+ [
+ ["def foo", "p :ok"],
+ ["class A; def", "foo(x); p x", "end"]
+ ].each do |buffer|
+ IRB::Source.new(buffer).code_block?.should == false
+ end
+ end
+
+ it "returns whether or not the accumulated source contains a syntax error" do
+ @source.syntax_error?.should == false
+ @source << "def foo"
+ @source.syntax_error?.should == false
+ @source << " def;"
+ @source.syntax_error?.should == true
+ end
+
+ it "returns the current code block indentation level" do
+ @source.level.should == 0
+ @source << "class A"
+ @source.level.should == 1
+ @source << " def foo"
+ @source.level.should == 2
+ @source << " p :ok"
+ @source.level.should == 2
+ @source << " end"
+ @source.level.should == 1
+ @source << " class B"
+ @source.level.should == 2
+ @source << " def bar"
+ @source.level.should == 3
+ @source << " p :ok; end"
+ @source.level.should == 2
+ @source << " end; end"
+ @source.level.should == 0
+ end
+
+ it "caches the reflection when possible" do
+ @source << "def foo"
+ reflection = @source.reflect
+ @source.level
+ @source.code_block?
+ @source.reflect.should == reflection
+
+ @source << "end"
+ @source.level
+ new_reflection = @source.reflect
+ new_reflection.should_not == reflection
+ @source.code_block?
+ @source.reflect.should == new_reflection
+
+ reflection = new_reflection
+
+ @source.pop
+ @source.level
+ new_reflection = @source.reflect
+ new_reflection.should_not == reflection
+ @source.syntax_error?
+ @source.reflect.should == new_reflection
+ end
+end
+
+describe "IRB::Source::Reflector" do
+ def reflect(source)
+ IRB::Source::Reflector.new(source)
+ end
+
+ it "returns whether or not the source is a valid code block" do
+ reflect("def foo").code_block?.should == false
+ reflect("def foo; p :ok").code_block?.should == false
+ reflect("def foo; p :ok; end").code_block?.should == true
+
+ reflect("if true").code_block?.should == false
+ reflect("p :ok if true").code_block?.should == true
+ end
+
+ it "returns whether or not the current session should be terminated" do
+ reflect("exit").terminate?.should == true
+ reflect("quit").terminate?.should == true
+ reflect("def foo; end; exit").terminate?.should == true
+ reflect("def foo; end; quit").terminate?.should == true
+
+ reflect("def foo; exit; end").terminate?.should == false
+ reflect("def foo; quit; end").terminate?.should == false
+ end
+
+ it "returns whether or not the source contains a syntax error, except a code block not ending" do
+ reflect("def;").syntax_error?.should == true
+ reflect("def;").syntax_error?.should == true
+ reflect("def foo").syntax_error?.should == false
+ reflect("class A; }").syntax_error?.should == true
+ reflect("class A; {" ).syntax_error?.should == false
+ reflect("class A def foo").syntax_error?.should == true
+ reflect("class A; def foo" ).syntax_error?.should == false
+ end
+
+ it "returns the actual syntax error message if one occurs" do
+ reflect("def foo").syntax_error.should == nil
+ reflect("}").syntax_error.should == "syntax error, unexpected '}'"
+ end
+
+ it "returns the code block indentation level" do
+ reflect("").level.should == 0
+ reflect("class A").level.should == 1
+ reflect("class A; def foo").level.should == 2
+ reflect("class A; def foo; p :ok").level.should == 2
+ reflect("class A; def foo; p :ok; end").level.should == 1
+ reflect("class A; class B").level.should == 2
+ reflect("class A; class B; def bar").level.should == 3
+ reflect("class A; class B; def bar; p :ok; end").level.should == 2
+ reflect("class A; class B; def bar; p :ok; end; end; end").level.should == 0
+ end
+
+ it "correctly increases and decreases the code block indentation level for keywords" do
+ [
+ "class A",
+ "module A",
+ "def foo",
+ "begin",
+ "if x == :ok",
+ "unless x == :ko",
+ "case x",
+ "while x",
+ "for x in xs",
+ "x.each do"
+ ].each do |open|
+ reflect(open).level.should == 1
+ reflect("#{open}\nend").level.should == 0
+ end
+ end
+
+ it "correctly increases and decreases the code block indentation level for literals" do
+ [
+ ["lambda { |x|", "}"],
+ ["{", "}"],
+ ['"#{', '}"'],
+ ["[", "]"]
+ ].each do |open, close|
+ reflect(open).level.should == 1
+ reflect("#{open}\n#{close}").level.should == 0
+ end
+ end
+end
Added: MacRuby/trunk/spec/dietrb/spec_helper.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/spec_helper.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/spec_helper.rb 2010-07-04 12:32:27 UTC (rev 4317)
@@ -0,0 +1,17 @@
+unless defined?(MSpec)
+ require 'rubygems'
+ require 'mspec'
+end
+
+ENV['SPECCING'] = 'true'
+
+root = File.expand_path('../../', __FILE__)
+if File.basename(root) == 'spec'
+ # running from the MacRuby repo
+ ROOT = File.expand_path('../../../', __FILE__)
+else
+ ROOT = root
+end
+$:.unshift File.join(ROOT, 'lib')
+
+require 'irb'
\ No newline at end of file
Modified: MacRuby/trunk/spec/macruby.mspec
===================================================================
--- MacRuby/trunk/spec/macruby.mspec 2010-07-02 13:13:23 UTC (rev 4316)
+++ MacRuby/trunk/spec/macruby.mspec 2010-07-04 12:32:27 UTC (rev 4317)
@@ -68,9 +68,11 @@
ENV['DYLD_LIBRARY_PATH'] = source_root
# Setup the proper load paths for lib and extensions
load_paths = %w{ -I. -I./lib -I./ext }
+ load_paths << '-I./ext/ripper/lib' # ripper specific load path fix
load_paths.concat Dir.glob('./ext/**/*.bundle').map { |filename| "-I#{File.dirname(filename)}" }.uniq
load_paths.concat(get(:flags)) if get(:flags)
set :flags, load_paths
+
# The default implementation to run the specs.
set :target, File.join(source_root, 'macruby')
end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100704/13bdca19/attachment-0001.html>
More information about the macruby-changes
mailing list