Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

127 lines (106 sloc) 3.581 kb
# 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@gmail.com>
require 'irb/formatter'
require 'irb/source'
module IRB
class Context
IGNORE_RESULT = :irb_ignore_result
attr_reader :object, :binding, :line, :level, :source
attr_accessor :formatter
def initialize(object, explicit_binding = nil)
@object = object
@binding = explicit_binding || object.instance_eval { binding }
@line = 1
@level = 0
clear_buffer
@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__)
eval(source, @binding, file, line)
end
def to_s
object_description = "`#{object.inspect}'"
object_description = "of class `#{object.class.name}'" if object_description.length > 32
"#<IRB::Context for object #{object_description}>"
end
alias_method :inspect, :to_s
def evaluate(source)
result = __evaluate__(source.to_s, '(irb)', @line - @source.buffer.size + 1)
unless IGNORE_RESULT == result
store_result(result)
output(formatter.result(result))
result
end
rescue Exception => e
store_exception(e)
output(formatter.exception(e))
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.
#
# For instance, this will continue:
#
# process_line("def foo") # => true
# process_line("quit") # => true
# process_line("end") # => true
#
# But at code block indentation level 0, `quit' means exit the runloop:
#
# process_line("quit") # => false
#
# If re-indenting the line results in a new line, the reformatted line and
# prompt are yielded to the optional block. This happens *before* the line
# is actually processed, so the caller (driver) has the opportunity to
# update the last printed line.
def process_line(line)
prompt_and_line = formatter.reindent_last_line(self) { @source << line }
yield(*prompt_and_line) if prompt_and_line && block_given?
return false if @source.terminate?
if @source.syntax_error?
output(formatter.syntax_error(@line, @source.syntax_error))
@source.pop
elsif @source.code_block?
evaluate(@source)
clear_buffer
end
@line += 1
@level = source.level
true
end
def driver
IRB::Driver.current
end
# Output is directed to the IRB::Driver.current driver’s output if a
# current driver is available. Otherwise it’s simply printed to $stdout.
def output(string)
if driver = self.driver
driver.output.puts(string)
else
puts(string)
end
end
def prompt(ignore_auto_indent = false)
formatter.prompt(self, ignore_auto_indent)
end
def input_line(line)
output(formatter.prompt(self) + line)
process_line(line)
end
def formatter
@formatter ||= IRB.formatter
end
def clear_buffer
@source = Source.new
end
def store_result(result)
@last_result_assigner.call(result)
end
def store_exception(exception)
@exception_assigner.call(exception)
end
end
end
Jump to Line
Something went wrong with that request. Please try again.