[macruby-changes] [4376] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Sat Jul 24 08:11:25 PDT 2010
Revision: 4376
http://trac.macosforge.org/projects/ruby/changeset/4376
Author: eloy.de.enige at gmail.com
Date: 2010-07-24 08:11:24 -0700 (Sat, 24 Jul 2010)
Log Message:
-----------
Update DietRB to 0.5.1 (ee35b7726a48c036e78623f111353ef2b8294a38)
Modified Paths:
--------------
MacRuby/trunk/bin/irb
MacRuby/trunk/lib/irb/completion.rb
MacRuby/trunk/lib/irb/context.rb
MacRuby/trunk/lib/irb/ext/completion.rb
MacRuby/trunk/lib/irb/ext/history.rb
MacRuby/trunk/lib/irb/version.rb
MacRuby/trunk/lib/irb.rb
MacRuby/trunk/spec/dietrb/context_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/spec_helper.rb
Added Paths:
-----------
MacRuby/trunk/lib/irb/driver/
MacRuby/trunk/lib/irb/driver/readline.rb
MacRuby/trunk/lib/irb/driver/socket.rb
MacRuby/trunk/lib/irb/driver/tty.rb
MacRuby/trunk/lib/irb/driver.rb
MacRuby/trunk/spec/dietrb/driver/
MacRuby/trunk/spec/dietrb/driver/readline_spec.rb
MacRuby/trunk/spec/dietrb/driver/tty_spec.rb
MacRuby/trunk/spec/dietrb/driver_spec.rb
Removed Paths:
-------------
MacRuby/trunk/lib/irb/ext/macruby.rb
Modified: MacRuby/trunk/bin/irb
===================================================================
--- MacRuby/trunk/bin/irb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/bin/irb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -2,41 +2,55 @@
require 'irb'
-unless ARGV.empty?
- require 'optparse'
-
- ignore_irbrc = false
-
- OptionParser.new do |opt|
- bin = File.basename($0)
- opt.banner = "Usage: #{bin} [options] [programfile] [arguments]"
- opt.on("-f", "Ignore ~/.irbrc") { |ignore| ignore_irbrc = ignore }
- opt.on("-r load-lib", "Loads the given library (same as `ruby -r')") { |lib| require lib }
- opt.on("-d", "Set $DEBUG to true (same as `ruby -d')") { $DEBUG = true }
- opt.on("-I path", "Add path to $LOAD_PATH") { |path| $LOAD_PATH.unshift(path) }
- opt.on("--noinspect", "Don't use inspect for output") { IRB.formatter.inspect = false }
- opt.on("--simple-prompt", "Simple prompt mode") { IRB.formatter.prompt = :simple }
- opt.on("--noprompt", "No prompt mode") { IRB.formatter.prompt = nil }
- opt.on("-v", "--version", "Print the version of #{bin}") do
- puts IRB::VERSION::DESCRIPTION
- exit
+IRB_CONTEXT_TOPLEVEL_ARGS = [self, TOPLEVEL_BINDING.dup]
+
+module IRB
+ # Just a namespace so not to pollute the toplevel namespace with lvars.
+ module Bin
+ driver = nil
+ ignore_irbrc = false
+
+ unless ARGV.empty?
+ require 'optparse'
+
+ OptionParser.new do |opt|
+ bin = File.basename($0)
+ opt.banner = "Usage: #{bin} [options] [programfile] [arguments]"
+ opt.on("-f", "Ignore ~/.irbrc") { |i| ignore_irbrc = i }
+ opt.on("-r load-lib", "Loads the given library (same as `ruby -r')") { |l| require l }
+ opt.on("-d", "Set $DEBUG to true (same as `ruby -d')") { $DEBUG = true }
+ opt.on("-I path", "Add path to $LOAD_PATH") { |p| $LOAD_PATH.unshift(p) }
+ opt.on("--driver name", "As driver, use one of: tty, readline, or socket") { |d| driver = d }
+ opt.on("--noinspect", "Don't use inspect for output") { IRB.formatter.inspect = false }
+ opt.on("--simple-prompt", "Simple prompt mode") { IRB.formatter.prompt = :simple }
+ opt.on("--noprompt", "No prompt mode") { IRB.formatter.prompt = nil }
+ opt.on("-v", "--version", "Print the version of #{bin}") do
+ $stdout.puts IRB::VERSION::DESCRIPTION
+ exit
+ end
+ end.parse!(ARGV)
end
- end.parse!(ARGV)
-end
-
-unless ignore_irbrc
- irbrc = File.expand_path("~/.irbrc")
- load(irbrc) if File.exist?(irbrc)
-end
-
-IRB.formatter.filter_from_backtrace << /^#{__FILE__}/
-
-if ARGV.empty?
- irb(self, TOPLEVEL_BINDING.dup)
-else
- path = ARGV.shift
- context = IRB::Context.new(self, TOPLEVEL_BINDING.dup)
- File.open(path, 'r') do |file|
- file.each_line { |line| context.input_line(line) }
+
+ unless ignore_irbrc
+ irbrc = File.expand_path("~/.irbrc")
+ load(irbrc) if File.exist?(irbrc)
+ end
+
+ IRB.formatter.filter_from_backtrace << /^#{__FILE__}/
+
+ if ARGV.empty?
+ driver ||= begin
+ require 'readline'
+ 'readline'
+ rescue LoadError
+ 'tty'
+ end
+ require "irb/driver/#{driver}"
+ irb(*IRB_CONTEXT_TOPLEVEL_ARGS)
+ else
+ path = ARGV.shift
+ context = IRB::Context.new(*IRB_CONTEXT_TOPLEVEL_ARGS)
+ File.open(path, 'r') { |f| f.each_line { |line| context.input_line(line) } }
+ end
end
end
\ No newline at end of file
Modified: MacRuby/trunk/lib/irb/completion.rb
===================================================================
--- MacRuby/trunk/lib/irb/completion.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/lib/irb/completion.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -1 +1 @@
-IRB.deprecated "The file `irb/completion' has moved to `irb/ext/ecompletion' and is loaded by default.", caller
\ No newline at end of file
+IRB.deprecated "The file `irb/completion' has moved to `irb/ext/completion' and is loaded by default.", caller
\ No newline at end of file
Modified: MacRuby/trunk/lib/irb/context.rb
===================================================================
--- MacRuby/trunk/lib/irb/context.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/lib/irb/context.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -5,28 +5,13 @@
# Copyright (C) 2009-2010, Eloy Duran <eloy.de.enige at gmail.com>
require 'irb/formatter'
-require 'readline'
module IRB
class Context
- class << self
- attr_accessor :current
-
- def make_current(context)
- # Messing with a current context is gonna bite me in the ass when we
- # get to multi-threading, but we'll it when we get there.
- before, @current = @current, context
- yield
- ensure
- @current = before
- end
-
- def processors
- @processors ||= []
- end
- end
+ IGNORE_RESULT = :irb_ignore_result
- attr_reader :object, :binding, :line, :source, :processors
+ attr_reader :object, :binding, :line, :source
+ attr_accessor :formatter
def initialize(object, explicit_binding = nil)
@object = object
@@ -34,8 +19,8 @@
@line = 1
clear_buffer
- @underscore_assigner = __evaluate__("_ = nil; proc { |val| _ = val }")
- @processors = self.class.processors.map { |processor| processor.new(self) }
+ @last_result_assigner = __evaluate__("_ = nil; proc { |val| _ = val }")
+ @exception_assigner = __evaluate__("e = exception = nil; proc { |ex| e = exception = ex }")
end
def __evaluate__(source, file = __FILE__, line = __LINE__)
@@ -44,33 +29,16 @@
def evaluate(source)
result = __evaluate__(source.to_s, '(irb)', @line - @source.buffer.size + 1)
- store_result(result)
- puts formatter.result(result)
- result
+ unless result == IGNORE_RESULT
+ store_result(result)
+ puts(formatter.result(result))
+ result
+ end
rescue Exception => e
store_exception(e)
- puts formatter.exception(e)
+ puts(formatter.exception(e))
end
- # Reads input and passes it to all processors.
- def readline
- input = Readline.readline(formatter.prompt(self), true)
- @processors.each { |processor| input = processor.input(input) }
- input
- rescue Interrupt
- clear_buffer
- ""
- end
-
- def run
- self.class.make_current(self) do
- while line = readline
- continue = process_line(line)
- break unless continue
- end
- end
- end
-
# Returns whether or not the user wants to continue the current runloop.
# This can only be done at a code block indentation level of 0.
#
@@ -88,7 +56,7 @@
return false if @source.terminate?
if @source.syntax_error?
- puts formatter.syntax_error(@line, @source.syntax_error)
+ puts(formatter.syntax_error(@line, @source.syntax_error))
@source.pop
elsif @source.code_block?
evaluate(@source)
@@ -99,13 +67,17 @@
true
end
+ def prompt
+ formatter.prompt(self)
+ end
+
def input_line(line)
- puts formatter.prompt(self) + line
+ puts(formatter.prompt(self) + line)
process_line(line)
end
def formatter
- IRB.formatter
+ @formatter ||= IRB.formatter
end
def clear_buffer
@@ -113,20 +85,11 @@
end
def store_result(result)
- @underscore_assigner.call(result)
+ @last_result_assigner.call(result)
end
def store_exception(exception)
- $e = $EXCEPTION = exception
+ @exception_assigner.call(exception)
end
end
-end
-
-module Kernel
- # Creates a new IRB::Context with the given +object+ and runs it.
- def irb(object, binding = nil)
- IRB::Context.new(object, binding).run
- end
-
- private :irb
-end
+end
\ No newline at end of file
Added: MacRuby/trunk/lib/irb/driver/readline.rb
===================================================================
--- MacRuby/trunk/lib/irb/driver/readline.rb (rev 0)
+++ MacRuby/trunk/lib/irb/driver/readline.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -0,0 +1,26 @@
+require 'readline'
+require 'irb/driver/tty'
+require 'irb/ext/history'
+require 'irb/ext/completion'
+
+module IRB
+ module Driver
+ class Readline < TTY
+
+ def initialize(input = $stdin, output = $stdout)
+ super
+ ::Readline.input = @input
+ ::Readline.output = @output
+ ::Readline.completion_proc = IRB::Completion.new
+ end
+
+ def readline
+ source = ::Readline.readline(context.prompt, true)
+ IRB::History.input(source)
+ source
+ end
+ end
+ end
+end
+
+IRB::Driver.current = IRB::Driver::Readline.new
Added: MacRuby/trunk/lib/irb/driver/socket.rb
===================================================================
--- MacRuby/trunk/lib/irb/driver/socket.rb (rev 0)
+++ MacRuby/trunk/lib/irb/driver/socket.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -0,0 +1,58 @@
+require 'irb/driver/tty'
+require 'socket'
+
+module IRB
+ module Driver
+ class Socket
+ class << self
+ attr_reader :instance
+
+ def run(object, binding)
+ @instance = new(object, binding)
+ @instance.run
+ end
+ end
+
+ # Initializes with the object and binding that each new connection will
+ # get as Context. The binding is shared, so local variables will stay
+ # around. The benefit of this is that a socket based irb session is most
+ # probably used to debug a running application in development. In this
+ # scenario it could be beneficial to keep local vars in between sessions.
+ #
+ # TODO see if that actually works out ok.
+ def initialize(object, binding, host = '127.0.0.1', port = 7829)
+ @object, @binding = object, binding
+ @host, @port = host, port
+ @server = TCPServer.new(host, port)
+ end
+
+ # TODO libedit doesn't use the right input and output, so we can't use Readline for now!!
+ def run
+ $stderr.puts "[!] Running IRB server on #{@host}:#{@port}"
+ loop do
+ connection = @server.accept
+ Thread.new do
+ # assign driver with connection to current thread and start runloop
+ IRB::Driver.current = TTY.new(connection, connection)
+ irb(@object, @binding)
+ connection.close
+ end
+ end
+ end
+ end
+ end
+end
+
+module Kernel
+ alias_method :irb_before_socket, :irb
+
+ def irb(object, binding = nil)
+ if IRB::Driver::Socket.instance.nil?
+ IRB::Driver::Socket.run(object, binding)
+ else
+ irb_before_socket(object, binding)
+ end
+ end
+
+ private :irb, :irb_before_socket
+end
\ No newline at end of file
Added: MacRuby/trunk/lib/irb/driver/tty.rb
===================================================================
--- MacRuby/trunk/lib/irb/driver/tty.rb (rev 0)
+++ MacRuby/trunk/lib/irb/driver/tty.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -0,0 +1,58 @@
+require 'irb/driver'
+
+module IRB
+ module Driver
+ class TTY
+ attr_reader :input, :output, :context_stack
+
+ def initialize(input = $stdin, output = $stdout)
+ @input = input
+ @output = output
+ @context_stack = []
+ end
+
+ def context
+ @context_stack.last
+ end
+
+ def readline
+ @output.print(context.prompt)
+ @input.gets
+ end
+
+ # TODO make it take the current context instead of storing it
+ def consume
+ readline
+ rescue Interrupt
+ context.clear_buffer
+ ""
+ end
+
+ # Feeds input into a given context.
+ #
+ # Ensures that the standard output object is a OutputRedirector, or a
+ # subclass thereof.
+ def run(context)
+ @context_stack << context
+ before, $stdout = $stdout, OutputRedirector.new unless $stdout.is_a?(OutputRedirector)
+ while line = consume
+ break unless context.process_line(line)
+ end
+ ensure
+ @context_stack.pop
+ $stdout = before if before
+ end
+ end
+ end
+end
+
+IRB::Driver.current = IRB::Driver::TTY.new
+
+module Kernel
+ # Creates a new IRB::Context with the given +object+ and runs it.
+ def irb(object, binding = nil)
+ IRB::Driver.current.run(IRB::Context.new(object, binding))
+ end
+
+ private :irb
+end
Added: MacRuby/trunk/lib/irb/driver.rb
===================================================================
--- MacRuby/trunk/lib/irb/driver.rb (rev 0)
+++ MacRuby/trunk/lib/irb/driver.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -0,0 +1,61 @@
+module IRB
+ module Driver
+ class << self
+ def current=(driver)
+ ThreadGroup.new.add(Thread.current)
+ Thread.current[:irb_driver] = driver
+ end
+
+ def current
+ current_thread = Thread.current
+ current_thread[:irb_driver] ||= begin
+ if group = current_thread.group
+ driver = nil
+ group.list.each do |thread|
+ break if driver = thread[:irb_driver]
+ end
+ driver
+ end
+ end
+ end
+ end
+
+ class OutputRedirector
+ def self.target
+ if driver = IRB::Driver.current
+ driver.output
+ else
+ $stderr
+ end
+ end
+
+ # A standard output object has only one mandatory method: write.
+ # It returns the number of characters written
+ def write(object)
+ string = object.respond_to?(:to_str) ? object : object.to_s
+ send_to_target :write, string
+ string.length
+ end
+
+ # if puts is not there, Ruby will automatically use the write
+ # method when calling Kernel#puts, but defining it has 2 advantages:
+ # - if puts is not defined, you cannot of course use $stdout.puts directly
+ # - (objc) when Ruby emulates puts, it calls write twice
+ # (once for the string and once for the carriage return)
+ # but here we send the calls to another thread so it's nice
+ # to be able to save up one (slow) interthread call
+ def puts(*args)
+ send_to_target :puts, *args
+ nil
+ end
+
+ # Override this if for your situation you need to dispatch from a thread
+ # in a special manner.
+ #
+ # TODO: for macruby send to main thread
+ def send_to_target(method, *args)
+ self.class.target.__send__(method, *args)
+ end
+ end
+ end
+end
\ No newline at end of file
Modified: MacRuby/trunk/lib/irb/ext/completion.rb
===================================================================
--- MacRuby/trunk/lib/irb/ext/completion.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/lib/irb/ext/completion.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -36,22 +36,23 @@
yield
}
+ attr_reader :source
+
+ def context
+ IRB::Driver.current.context
+ end
+
# Returns an array of possible completion results, with the current
# IRB::Context.
#
# This is meant to be used with Readline which takes a completion proc.
- def self.call(source)
- new(IRB::Context.current, source).results
+ def call(source)
+ @source = source
+ results
end
- attr_reader :context, :source
-
- def initialize(context, source)
- @context, @source = context, source
- end
-
def evaluate(s)
- @context.__evaluate__(s)
+ context.__evaluate__(s)
end
def local_variables
@@ -59,7 +60,7 @@
end
def instance_methods
- @context.object.methods.map(&:to_s)
+ context.object.methods.map(&:to_s)
end
def instance_methods_of(klass)
@@ -190,5 +191,5 @@
# * Hash: = and >
Readline.basic_word_break_characters= " \t\n`<;|&("
end
- Readline.completion_proc = IRB::Completion
-end
\ No newline at end of file
+ # Readline.completion_proc = IRB::Completion
+end
Modified: MacRuby/trunk/lib/irb/ext/history.rb
===================================================================
--- MacRuby/trunk/lib/irb/ext/history.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/lib/irb/ext/history.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -7,91 +7,86 @@
# Portions Copyright (C) 2006-2010 Ben Bleything <ben at bleything.net> (Kernel#history & Kernel#history!)
module IRB
- class History
+ module History
class << self
attr_accessor :file, :max_entries_in_overview
- def current
- IRB::Context.current.processors.find do |processor|
- processor.is_a?(IRB::History)
- end
+ def setup
+ to_a.each do |source|
+ Readline::HISTORY.push(source)
+ end if Readline::HISTORY.to_a.empty?
end
- end
-
- def initialize(context)
- @context = context
- to_a.each do |source|
- Readline::HISTORY.push(source)
- end if Readline::HISTORY.to_a.empty?
- end
-
- def input(source)
- File.open(self.class.file, "a") { |f| f.puts(source) }
- source
- end
-
- def to_a
- file = self.class.file
- File.exist?(file) ? File.read(file).split("\n") : []
- end
-
- def clear!
- File.open(self.class.file, "w") { |f| f << "" }
- Readline::HISTORY.clear
- end
-
- def history(number_of_entries = max_entries_in_overview)
- history_size = Readline::HISTORY.size
- start_index = 0
+ def context
+ IRB::Driver.current.context
+ end
- # always remove one extra, because that's the `history' command itself
- if history_size <= number_of_entries
- end_index = history_size - 2
- else
- end_index = history_size - 2
- start_index = history_size - number_of_entries - 1
+ def input(source)
+ File.open(file, "a") { |f| f.puts(source) }
+ source
end
- start_index.upto(end_index) do |i|
- puts "#{i}: #{Readline::HISTORY[i]}"
+ def to_a
+ File.exist?(file) ? File.read(file).split("\n") : []
end
- end
-
- def history!(entry_or_range)
- # we don't want to execute history! again
- @context.clear_buffer
- if entry_or_range.is_a?(Range)
- entry_or_range.to_a.each do |i|
- @context.input_line(Readline::HISTORY[i])
+ def clear!
+ File.open(file, "w") { |f| f << "" }
+ Readline::HISTORY.clear
+ end
+
+ def history(number_of_entries = max_entries_in_overview)
+ history_size = Readline::HISTORY.size
+ start_index = 0
+
+ # always remove one extra, because that's the `history' command itself
+ if history_size <= number_of_entries
+ end_index = history_size - 2
+ else
+ end_index = history_size - 2
+ start_index = history_size - number_of_entries - 1
end
- else
- @context.input_line(Readline::HISTORY[entry_or_range])
+
+ start_index.upto(end_index) do |i|
+ puts "#{i}: #{Readline::HISTORY[i]}"
+ end
end
+
+ def history!(entry_or_range)
+ # we don't want to execute history! again
+ context.clear_buffer
+
+ if entry_or_range.is_a?(Range)
+ entry_or_range.to_a.each do |i|
+ context.input_line(Readline::HISTORY[i])
+ end
+ else
+ context.input_line(Readline::HISTORY[entry_or_range])
+ end
+ end
end
end
end
module Kernel
def history(number_of_entries = IRB::History.max_entries_in_overview)
- IRB::History.current.history(number_of_entries)
- nil
+ IRB::History.history(number_of_entries)
+ IRB::Context::IGNORE_RESULT
end
alias_method :h, :history
def history!(entry_or_range)
- IRB::History.current.history!(entry_or_range)
- nil
+ IRB::History.history!(entry_or_range)
+ IRB::Context::IGNORE_RESULT
end
alias_method :h!, :history!
def clear_history!
- IRB::History.current.clear!
- nil
+ IRB::History.clear!
+ true
end
end
-IRB::Context.processors << IRB::History
IRB::History.file = File.expand_path("~/.irb_history")
-IRB::History.max_entries_in_overview = 50
\ No newline at end of file
+IRB::History.max_entries_in_overview = 50
+IRB::History.setup
\ No newline at end of file
Deleted: MacRuby/trunk/lib/irb/ext/macruby.rb
===================================================================
--- MacRuby/trunk/lib/irb/ext/macruby.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/lib/irb/ext/macruby.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -1,25 +0,0 @@
-# MacRuby implementation of IRB.
-#
-# This file is covered by the Ruby license. See COPYING for more details.
-#
-# Copyright (C) 2009-2010, Eloy Duran <eloy.de.enige at gmail.com>
-
-framework 'AppKit'
-
-module IRB
- class Context
- alias_method :_run, :run
-
- def run
- if NSApplication.sharedApplication.running?
- _run
- else
- Thread.new do
- _run
- NSApplication.sharedApplication.terminate(self)
- end
- NSApplication.sharedApplication.run
- end
- end
- end
-end
\ No newline at end of file
Modified: MacRuby/trunk/lib/irb/version.rb
===================================================================
--- MacRuby/trunk/lib/irb/version.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/lib/irb/version.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -8,8 +8,8 @@
module VERSION #:nodoc:
NAME = 'DietRB'
MAJOR = 0
- MINOR = 4
- TINY = 7
+ MINOR = 5
+ TINY = 1
STRING = [MAJOR, MINOR, TINY].join('.')
DESCRIPTION = "#{NAME} (#{STRING})"
Modified: MacRuby/trunk/lib/irb.rb
===================================================================
--- MacRuby/trunk/lib/irb.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/lib/irb.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -10,13 +10,6 @@
require 'irb/deprecated'
-require 'irb/ext/history'
-require 'irb/ext/completion'
-
-# if !ENV['SPECCING'] && defined?(RUBY_ENGINE) && RUBY_ENGINE == "macruby"
-# require 'irb/ext/macruby'
-# end
-
module IRB
class << self
# This is just here for so the ruby 1.9 IRB will seemingly work, but actually
Modified: MacRuby/trunk/spec/dietrb/context_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/context_spec.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/spec/dietrb/context_spec.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -1,22 +1,6 @@
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
@@ -28,6 +12,7 @@
describe "IRB::Context" do
before do
@context = IRB::Context.new(main)
+ @context.extend(OutputStubMixin)
end
it "initializes with an object and stores a copy of its binding" do
@@ -50,37 +35,15 @@
@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
+ @context.extend(OutputStubMixin)
IRB.formatter = IRB::Formatter.new
end
@@ -112,11 +75,11 @@
}.should_not.raise_error
end
- it "assigns the last raised exception to the global variable `$EXCEPTION' / `$e'" do
+ it "assigns the last raised exception to the variables `exception' / `e'" do
@context.evaluate("DoesNotExist")
- $EXCEPTION.class.should == NameError
- $EXCEPTION.message.should include('DoesNotExist')
- $e.should == $EXCEPTION
+ @context.__evaluate__("exception").class.should == NameError
+ @context.__evaluate__("exception").message.should include('DoesNotExist')
+ @context.__evaluate__("e").should == @context.__evaluate__("exception")
end
it "prints the exception that occurs" do
@@ -133,59 +96,31 @@
@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
+ it "ignores the result if it's IRB::Context::IGNORE_RESULT" do
+ @context.evaluate(":bananas")
+ @context.evaluate("IRB::Context::IGNORE_RESULT").should == nil
+ @context.printed.should == "=> :bananas\n"
+ @context.evaluate("_").should == :bananas
end
end
describe "IRB::Context, when receiving input" do
before do
@context = IRB::Context.new(main)
+ @context.extend(InputStubMixin)
+ @context.extend(OutputStubMixin)
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
+ it "clears the source buffer" do
+ @context.process_line("def foo")
+ @context.clear_buffer
+ @context.source.to_s.should == ""
end
it "increases the current line number" do
@@ -208,14 +143,11 @@
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 '}'"
+ @context.printed.should == "SyntaxError: compile error\n(irb):2: syntax error, unexpected '}'\n"
end
it "returns whether or not the runloop should continue, but only if the level is 0" do
@@ -226,19 +158,9 @@
@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"
+ it "inputs a line to be processed" do
+ expected = "#{@context.formatter.prompt(@context)}2 * 21\n=> 42\n"
+ @context.input_line("2 * 21")
+ @context.printed.should == expected
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/driver/readline_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/driver/readline_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/driver/readline_spec.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -0,0 +1,70 @@
+require File.expand_path("../../spec_helper", __FILE__)
+require "irb/driver/readline"
+
+module Readline
+ extend InputStubMixin
+ extend OutputStubMixin
+
+ def self.input=(input)
+ @given_input = input
+ end
+
+ def self.given_input
+ @given_input
+ end
+
+ def self.output=(output)
+ @given_output = output
+ end
+
+ def self.given_output
+ @given_output
+ end
+
+ def self.use_history=(use_history)
+ @use_history = use_history
+ end
+
+ def self.use_history
+ @use_history
+ end
+
+ def self.readline(prompt, use_history)
+ @use_history = use_history
+ print prompt
+ @input.shift
+ end
+end
+
+describe "IRB::Driver::Readline" do
+ before do
+ @driver = IRB::Driver::Readline.new(InputStub.new, OutputStub.new)
+ @context = IRB::Context.new(Object.new)
+ @driver.context_stack << @context
+ end
+
+ it "is a subclass of IRB::Driver::TTY" do
+ IRB::Driver::Readline.superclass.should == IRB::Driver::TTY
+ end
+
+ it "assigns the given input and output to the Readline module" do
+ Readline.given_input.should == @driver.input
+ Readline.given_output.should == @driver.output
+ end
+
+ it "assigns a completion object" do
+ Readline.completion_proc.class.should == IRB::Completion
+ end
+
+ it "reads a line through the Readline module" do
+ Readline.stub_input "nom nom nom"
+ @driver.readline.should == "nom nom nom"
+ end
+
+ it "tells the Readline module to use the history" do
+ Readline.use_history = false
+ Readline.stub_input "nom nom nom"
+ @driver.readline
+ Readline.use_history.should == true
+ end
+end
Added: MacRuby/trunk/spec/dietrb/driver/tty_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/driver/tty_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/driver/tty_spec.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -0,0 +1,70 @@
+require File.expand_path('../../spec_helper', __FILE__)
+require 'irb/driver/tty'
+
+describe "IRB::Driver::TTY" do
+ before do
+ @driver = IRB::Driver::TTY.new(InputStub.new, OutputStub.new)
+ @context = IRB::Context.new(Object.new)
+ @driver.context_stack << @context
+ end
+
+ it "prints the prompt and reads a line of input" do
+ @driver.input.stub_input "calzone"
+ @driver.readline.should == "calzone"
+ @driver.output.printed.should == @context.prompt
+ end
+
+ it "consumes input" do
+ @driver.input.stub_input "calzone"
+ @driver.consume.should == "calzone"
+ end
+
+ it "clears the context buffer if an Interrupt signal is received while consuming input" do
+ @context.process_line("class A")
+ def @driver.readline; raise Interrupt; end
+ @driver.consume.should == ""
+ @context.source.to_s.should == ""
+ end
+end
+
+describe "IRB::Driver::TTY, when starting the runloop" do
+ before do
+ @driver = IRB::Driver::TTY.new(InputStub.new, OutputStub.new)
+ IRB::Driver.current = @driver
+ @context = IRB::Context.new(Object.new)
+ end
+
+ it "makes the given context the current one, for this driver, for the duration of the runloop" do
+ $from_context = nil
+ @driver.input.stub_input "$from_context = IRB::Driver.current.context"
+ @driver.run(@context)
+ $from_context.should == @context
+ IRB::Driver.current.context.should == nil
+ end
+
+ it "feeds input into a given context" do
+ $from_context = false
+ @driver.input.stub_input "$from_context = true", "exit"
+ @driver.run(@context)
+ $from_context.should == true
+ end
+
+ it "makes sure there's a global output redirector while running a context" do
+ before = $stdout
+ $from_context = nil
+ @driver.input.stub_input "$from_context = $stdout", "exit"
+ @driver.run(@context)
+ $from_context.class == IRB::Driver::OutputRedirector
+ $stdout.should == before
+ end
+end
+
+# describe "Kernel::irb" do
+# it "creates a new context for the given object and runs it" do
+# IRB.io = CaptureIO.new
+# IRB.io.stub_input("::IRBRan = self")
+# o = Object.new
+# irb(o)
+# IRBRan.should == o
+# end
+# end
\ No newline at end of file
Added: MacRuby/trunk/spec/dietrb/driver_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/driver_spec.rb (rev 0)
+++ MacRuby/trunk/spec/dietrb/driver_spec.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -0,0 +1,65 @@
+require File.expand_path('../spec_helper', __FILE__)
+require 'irb/driver'
+
+describe "IRB::Driver" do
+ before :all do
+ @driver = StubDriver.new
+ IRB::Driver.current = @driver
+ end
+
+ it "assigns the driver for the current thread" do
+ Thread.current[:irb_driver].should == @driver
+ end
+
+ it "returns the same driver for child threads" do
+ Thread.new do
+ IRB::Driver.current = other = StubDriver.new
+ Thread.new { IRB::Driver.current.should == other }.join
+ end.join
+ Thread.new { IRB::Driver.current.should == @driver }.join
+ end
+end
+
+describe "IRB::Driver::OutputRedirector" do
+ before :each do
+ @driver = StubDriver.new
+ @driver.output = OutputStub.new
+ IRB::Driver.current = @driver
+
+ @redirector = IRB::Driver::OutputRedirector.new
+ end
+
+ it "returns $stderr as the target if no current driver could be found" do
+ IRB::Driver.current = nil
+ IRB::Driver::OutputRedirector.target.should == $stderr
+ end
+
+ it "returns the current driver's output as the target" do
+ IRB::Driver::OutputRedirector.target.should == @driver.output
+ end
+
+ it "forwards method calls to the current target" do
+ @redirector.send_to_target(:eql?, @driver.output).should == true
+ end
+
+ it "writes to the current target's output" do
+ @redirector.write("strawberry coupe")
+ @driver.output.printed.should == "strawberry coupe"
+ end
+
+ it "returns the amount of bytes written" do
+ @redirector.write("banana coupe").should == 12
+ end
+
+ it "coerces an object to a string before writing" do
+ o = Object.new
+ def o.to_s; "cherry coupe"; end
+ @redirector.write(o)
+ @driver.output.printed.should == "cherry coupe"
+ end
+
+ it "forwards puts to the current target's output" do
+ @redirector.puts("double", "coupe")
+ @driver.output.printed.should == "double\ncoupe\n"
+ end
+end
\ No newline at end of file
Modified: MacRuby/trunk/spec/dietrb/ext/completion_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/ext/completion_spec.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/spec/dietrb/ext/completion_spec.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -1,9 +1,11 @@
require File.expand_path('../../spec_helper', __FILE__)
+require 'irb/driver'
require 'irb/ext/completion'
module CompletionHelper
def complete(str)
- IRB::Completion.new(@context, str).results
+ # IRB::Completion.new(@context, str).results
+ @completion.call(str)
end
def imethods(klass, receiver = nil)
@@ -35,12 +37,14 @@
describe "IRB::Completion" do
extend CompletionHelper
- before do
+ before :all do
+ @completion = IRB::Completion.new
@context = IRB::Context.new(Playground.new)
+ IRB::Driver.current = StubDriver.new(@context)
end
it "quacks like a Proc" do
- IRB::Completion.call('//.').should == imethods(Regexp, '//')
+ @completion.call('//.').should == imethods(Regexp, '//')
end
describe "when doing a method call on an explicit receiver," do
Modified: MacRuby/trunk/spec/dietrb/ext/history_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/ext/history_spec.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/spec/dietrb/ext/history_spec.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -1,6 +1,10 @@
require File.expand_path('../../spec_helper', __FILE__)
+require 'readline'
require "tempfile"
+require 'irb/ext/history'
+require 'irb/driver'
+
describe "IRB::History, by default," do
it "stores the history in ~/.irb_history" do
IRB::History.file.should == File.expand_path("~/.irb_history")
@@ -11,7 +15,7 @@
before do
@file = Tempfile.new("irb_history.txt")
IRB::History.file = @file.path
- @history = IRB::History.new(nil)
+ @history = IRB::History
end
after do
@@ -54,8 +58,8 @@
@history.input "puts :ok"
@history.input "foo(x)"
- IRB::History.new(nil)
- IRB::History.new(nil)
+ IRB::History.setup
+ IRB::History.setup
Readline::HISTORY.to_a.should == ["puts :ok", "foo(x)"]
end
@@ -70,25 +74,16 @@
end
end
-class IRB::History
- def printed
- @printed ||= ""
+module IRB::History
+ class << self
+ def clear!
+ @cleared = true
+ end
+
+ def cleared?
+ @cleared
+ end
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
@@ -115,24 +110,22 @@
IRB::History.max_entries_in_overview = 5
- @context = IRB::Context.new(Object.new)
- IRB::Context.current = @context
+ IRB::History.extend(OutputStubMixin)
+ IRB::History.clear_printed!
- @history = @context.processors.find { |p| p.is_a?(IRB::History) }
+ @context = IRB::Context.new(Object.new)
+ @context.extend(OutputStubMixin)
+ IRB::Driver.current = StubDriver.new(@context)
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
+ history.should == IRB::Context::IGNORE_RESULT
end
- it "prints a formatted list with, by default IRB::History.max_entries_in_overview, number of history entries" do
+ it "prints a formatted list with IRB::History.max_entries_in_overview number of history entries" do
history
- @history.printed.should == %{
+ IRB::History.printed.should == %{
2: class AAA
3: def bar
4: :ok
@@ -144,7 +137,7 @@
it "prints a formatted list of N most recent history entries" do
history(7)
- @history.printed.should == %{
+ IRB::History.printed.should == %{
0: puts :ok
1: x = foo(x)
2: class AAA
@@ -158,7 +151,7 @@
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 == %{
+ IRB::History.printed.should == %{
0: puts :ok
1: x = foo(x)
2: class AAA
@@ -182,6 +175,6 @@
it "clears the history and history file" do
clear_history!
- @history.cleared?.should == true
+ IRB::History.cleared?.should == true
end
end
\ No newline at end of file
Modified: MacRuby/trunk/spec/dietrb/formatter_spec.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/formatter_spec.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/spec/dietrb/formatter_spec.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -40,13 +40,15 @@
it "does not filter the backtrace if $DEBUG is true" do
begin
- before, $DEBUG = $DEBUG, true
+ stderr, $stderr = $stderr, OutputStub.new
+ debug, $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
+ $stderr = stderr
+ $DEBUG = debug
end
end
@@ -67,7 +69,7 @@
def object.inspect; @inspected = true; "Never called!"; end
def object.__id__; 2158110700; end
- @formatter.result(object).should == "=> #<Object:0x101444fd8>"
+ @formatter.result(object).should == "=> #<#{object.class.name}:0x101444fd8>"
object.instance_variable_get(:@inspected).should_not == true
end
Modified: MacRuby/trunk/spec/dietrb/spec_helper.rb
===================================================================
--- MacRuby/trunk/spec/dietrb/spec_helper.rb 2010-07-24 03:06:27 UTC (rev 4375)
+++ MacRuby/trunk/spec/dietrb/spec_helper.rb 2010-07-24 15:11:24 UTC (rev 4376)
@@ -14,4 +14,62 @@
end
$:.unshift File.join(ROOT, 'lib')
-require 'irb'
\ No newline at end of file
+require 'irb'
+
+module InputStubMixin
+ def stub_input(*input)
+ @input = input
+ end
+
+ def readline(prompt)
+ # print prompt
+ @input.shift
+ end
+
+ def gets
+ @input.shift
+ end
+end
+
+class InputStub
+ include InputStubMixin
+end
+
+module OutputStubMixin
+ def printed
+ @printed ||= ''
+ end
+
+ def write(string)
+ printed << string
+ end
+
+ def print(string)
+ printed << string
+ end
+
+ def puts(*args)
+ print "#{args.join("\n")}\n"
+ end
+
+ def clear_printed!
+ @printed = ''
+ end
+end
+
+class OutputStub
+ include OutputStubMixin
+end
+
+class StubDriver
+ attr_reader :context
+ attr_writer :output
+
+ def initialize(context = nil)
+ @context = context
+ end
+
+ def output
+ @output || $stdout
+ end
+end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100724/fa8b8bde/attachment-0001.html>
More information about the macruby-changes
mailing list