Permalink
Browse files

Some final cleaning of the hacking spree, before speccing

  • Loading branch information...
alloy committed Jul 14, 2010
1 parent d3513a6 commit abfd9dfebcc5649b225f4fc2b9676e36ada7bcd7
Showing with 81 additions and 101 deletions.
  1. +3 −1 bin/dietrb
  2. +5 −9 lib/irb/context.rb
  3. +60 −0 lib/irb/driver.rb
  4. +1 −11 lib/irb/driver/socket.rb
  5. +7 −80 lib/irb/driver/tty.rb
  6. +5 −0 spec/driver/tty_spec.rb
View
@@ -32,7 +32,9 @@ end
IRB.formatter.filter_from_backtrace << /^#{__FILE__}/
if ARGV.empty?
- require 'irb/driver/readline'
+ # require 'irb/driver/readline'
+ # require 'irb/driver/tty'
+ require 'irb/driver/socket'
else
path = ARGV.shift
require 'irb/driver/file'
View
@@ -15,7 +15,7 @@ def processors
end
attr_reader :object, :binding, :line, :source, :processors
- attr_accessor :driver, :formatter
+ attr_accessor :formatter
def initialize(object, explicit_binding = nil)
@object = object
@@ -34,11 +34,11 @@ def __evaluate__(source, file = __FILE__, line = __LINE__)
def evaluate(source)
result = __evaluate__(source.to_s, '(irb)', @line - @source.buffer.size + 1)
store_result(result)
- output.puts(formatter.result(result))
+ puts(formatter.result(result))
result
rescue Exception => e
store_exception(e)
- output.puts(formatter.exception(e))
+ puts(formatter.exception(e))
end
# Returns whether or not the user wants to continue the current runloop.
@@ -61,7 +61,7 @@ def process_line(line)
return false if @source.terminate?
if @source.syntax_error?
- output.puts(formatter.syntax_error(@line, @source.syntax_error))
+ puts(formatter.syntax_error(@line, @source.syntax_error))
@source.pop
elsif @source.code_block?
evaluate(@source)
@@ -77,14 +77,10 @@ def prompt
end
def input_line(line)
- output.puts(formatter.prompt(self) + line)
+ puts(formatter.prompt(self) + line)
process_line(line)
end
- def output
- @driver || $stdout
- end
-
def formatter
@formatter ||= IRB.formatter
end
View
@@ -0,0 +1,60 @@
+module IRB
+ class << self
+ attr_accessor :driver_class
+
+ def driver=(driver)
+ Thread.current[:irb_driver] = driver
+ end
+
+ def driver
+ current_thread = Thread.current
+ current_thread[:irb_driver] ||= begin
+ if group = current_thread.group
+ group.list.each do |thread|
+ break(driver) if driver = thread[:irb_driver]
+ end
+ end
+ end
+ end
+ end
+
+ module Driver
+ class OutputRedirector
+ def self.target
+ if driver = IRB.driver
+ 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
View
@@ -3,16 +3,6 @@
module IRB
module Driver
- class SocketTTY < TTY
- # We don't want to put the real standard output object on the
- # OutputRedirector target stack.
- def assign_output_redirector!
- before = $stdout
- $stdout = IRB::Driver::OutputRedirector.new
- before
- end
- end
-
class Socket
# Initializes with the object and binding that each new connection will
# get as Context. The binding is shared, so local variables will stay
@@ -34,7 +24,7 @@ def run
connection = @server.accept
Thread.new do
# assign driver with connection to current thread and start runloop
- IRB.driver = SocketTTY.new(connection, connection)
+ IRB.driver = TTY.new(connection, connection)
irb(@object, @binding)
connection.close
end
View
@@ -1,80 +1,13 @@
+require 'irb/driver'
+
module IRB
- class << self
- attr_accessor :driver_class
-
- def driver=(driver)
- Thread.current[:irb_driver] = driver
- end
-
- def driver
- current_thread = Thread.current
- current_thread[:irb_driver] ||= begin
- driver = nil
- if group = current_thread.group
- group.list.each do |thread|
- break if driver = thread[:irb_driver]
- end
- end
- driver || driver_class.new
- end
- end
- end
-
module Driver
- class OutputRedirector
- # The output object for the current thread.
- def self.target=(output)
- Thread.current[:irb_stdout_target] = output
- end
-
- # TODO cache, or not to cache?
- def self.target
- current_thread = Thread.current
- if target = current_thread[:irb_stdout_target]
- elsif group = current_thread.group
- group.list.each do |thread|
- break if target = thread[:irb_stdout_target]
- end
- end
- target || $stderr
- 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
-
class TTY
- attr_accessor :current_context
+ attr_reader :input, :output
def initialize(input = $stdin, output = $stdout)
@input = input
@output = output
- OutputRedirector.target = output
@thread_group = ThreadGroup.new
@thread_group.add(Thread.current)
@@ -104,7 +37,6 @@ def print(*args)
def run(context)
ensure_output_redirector do
- context.driver = self
while line = consume(context)
continue = context.process_line(line)
break unless continue
@@ -115,27 +47,22 @@ def run(context)
# Ensure that the standard output object is a OutputRedirector. If it's
# already a OutputRedirector, do nothing.
def ensure_output_redirector
- before = assign_output_redirector! unless $stdout.is_a?(IRB::Driver::OutputRedirector)
+ unless $stdout.is_a?(IRB::Driver::OutputRedirector)
+ before, $stdout = $stdout, IRB::Driver::OutputRedirector.new
+ end
yield
ensure
$stdout = before if before
end
-
- def assign_output_redirector!
- before = IRB::Driver::OutputRedirector.target = $stdout
- $stdout = IRB::Driver::OutputRedirector.new
- before
- end
end
end
end
-IRB.driver_class = IRB::Driver::TTY
+IRB.driver = 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.run(IRB::Context.new(IRB.driver, object, binding))
IRB.driver.run(IRB::Context.new(object, binding))
end
View
@@ -0,0 +1,5 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+describe "IRB::Driver::TTY" do
+
+end

0 comments on commit abfd9df

Please sign in to comment.